Fix assembler, update tests, update roms, add back nogui mode for speed.

This commit is contained in:
zongor 2025-12-07 15:29:49 -08:00
parent 07528b1f3f
commit 0d30ea292a
43 changed files with 538 additions and 993 deletions

View File

@ -2,6 +2,9 @@
PLATFORM ?= linux PLATFORM ?= linux
BUILD_MODE ?= debug # 'debug' or 'release' BUILD_MODE ?= debug # 'debug' or 'release'
# Ensure BUILD_MODE is fixed before any conditionals
$(eval BUILD_MODE := $(or $(BUILD_MODE),debug))
# --- DIRECTORIES --- # --- DIRECTORIES ---
SRC_DIR := src SRC_DIR := src
BUILD_DIR := build/$(PLATFORM) BUILD_DIR := build/$(PLATFORM)
@ -107,13 +110,11 @@ DEPS := $(VM_OBJS:.o=.d) $(PLATFORM_OBJ:.o=.d)
# Default target # Default target
all: $(TARGET) all: $(TARGET)
# 'debug' target — just set BUILD_MODE and build debug:
debug: BUILD_MODE=debug $(MAKE) BUILD_MODE=debug all
debug: $(TARGET)
# 'release' target — just set BUILD_MODE and build release:
release: BUILD_MODE=release $(MAKE) BUILD_MODE=release all
release: $(TARGET)
# --- COMPILE VM CORE (freestanding) --- # --- COMPILE VM CORE (freestanding) ---
$(BUILD_DIR)/vm/%.o: $(SRC_DIR)/vm/%.c $(BUILD_DIR)/vm/%.o: $(SRC_DIR)/vm/%.c
@ -155,11 +156,11 @@ clean-all:
# --- TEST COMPILATION TARGET --- # --- TEST COMPILATION TARGET ---
# Compiles all .asm.lisp test files to .rom using the debug VM executable # Compiles all .asm.lisp test files to .rom using the debug VM executable
# Usage: make compile-tests PLATFORM=linux # Usage: make tests PLATFORM=linux
compile-tests: $(BUILD_DIR)/undar-$(PLATFORM)$(TARGET_SUFFIX) tests: $(BUILD_DIR)/undar-$(PLATFORM)$(TARGET_SUFFIX)
@echo "Compiling test assembly files for $(PLATFORM)..." @echo "Compiling test assembly files for $(PLATFORM)..."
@for f in ./test/*.asm.lisp; do \ @for f in ./test/*.ul.ir; do \
base=$$(basename "$$f" .asm.lisp); \ base=$$(basename "$$f" .ul.ir); \
echo " [$$base] $$f -> ./test/$$base.rom"; \ echo " [$$base] $$f -> ./test/$$base.rom"; \
$(BUILD_DIR)/undar-$(PLATFORM)$(TARGET_SUFFIX) "$$f" -o "./test/$$base.rom"; \ $(BUILD_DIR)/undar-$(PLATFORM)$(TARGET_SUFFIX) "$$f" -o "./test/$$base.rom"; \
done done

View File

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

View File

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

View File

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

View File

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

View File

@ -41,9 +41,9 @@ print_section "zre ($FILENAME.t.ul)"
echo "test input" | time ../build/old/zre -t "$FILENAME.ul" echo "test input" | time ../build/old/zre -t "$FILENAME.ul"
# Undâr Implementation (inline assembled) # Undâr Implementation (inline assembled)
print_section "undar ($FILENAME.asm.lisp)" print_section "undar ($FILENAME.ul.ir)"
echo "test input" | time ../build/linux/undar-linux-release "../test/$FILENAME.asm.lisp" echo "test input" | time ../build/linux/undar-linux-release -t "../test/$FILENAME.ul.ir"
# Undâr Implementation (binary) # Undâr Implementation (binary)
print_section "undar ($FILENAME.rom)" print_section "undar ($FILENAME.rom)"
echo "test input" | time ../build/linux/undar-linux-release "../test/$FILENAME.rom" echo "test input" | time ../build/linux/undar-linux-release -t "../test/$FILENAME.rom"

View File

@ -1 +1 @@
print(tostring(1 + 2)) print(tostring(1.0 + 2.0))

View File

@ -1 +1 @@
print((1 + 2) . "\n"); print((1.0 + 2.0) . "\n");

View File

@ -1 +1 @@
print(str(1 + 2)) print(str(1.0 + 2.0))

View File

@ -1,2 +1,2 @@
let sum = 1 + 2; let sum = 1.0 + 2.0;
print sum; print sum;

View File

@ -29,6 +29,11 @@ i32 console_read(void *data, u8 *buffer, u32 size) {
i32 console_write(void *data, const u8 *buffer, u32 size) { i32 console_write(void *data, const u8 *buffer, u32 size) {
USED(data); USED(data);
if (size > MEMORY_SIZE) {
return 0;
}
for (u32 i = 0; i < size; i++) { for (u32 i = 0; i < size; i++) {
putchar(buffer[i]); putchar(buffer[i]);
} }

View File

@ -129,6 +129,38 @@ bool compileAndSave(const char *source_file, const char *output_file, VM *vm) {
return true; return true;
} }
#ifdef STATIC
#define SYMBOLS_COUNT 2048
Symbol symbols[SYMBOLS_COUNT];
#endif
void symbol_table_init(SymbolTable *t) {
#ifdef STATIC
memset(symbols, 0, SYMBOLS_COUNT*sizeof(Symbol));
t->symbols = symbols;
t->count = 0;
t->capacity = SYMBOLS_COUNT;
#else
t->symbols = calloc(16, sizeof(Symbol));
t->count = 0;
t->capacity = 16;
#endif
}
bool resize_or_check_size(SymbolTable *table) {
#ifdef STATIC
if (table->count >= table->capacity) {
return false;
}
#else
if (table->count >= table->capacity) {
table->capacity *= 2;
table->symbols = realloc(table->symbols, table->capacity * sizeof(Symbol));
}
#endif
return true;
}
// Function to assemble and optionally save // Function to assemble and optionally save
bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) { bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) {
FILE *f = fopen(source_file, "rb"); FILE *f = fopen(source_file, "rb");
@ -151,7 +183,12 @@ bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) {
source[read] = '\0'; source[read] = '\0';
fclose(f); fclose(f);
assemble(vm, source); SymbolTable table = {0};
symbol_table_init(&table);
assemble(vm, &table, source);
#ifndef STATIC
free(table.symbols);
#endif
if (output_file) { if (output_file) {
if (!saveVM(output_file, vm)) { if (!saveVM(output_file, vm)) {
@ -167,6 +204,7 @@ i32 main(i32 argc, char *argv[]) {
bool dump_rom = false; bool dump_rom = false;
char *input_file = nil; char *input_file = nil;
char *output_file = nil; char *output_file = nil;
bool terminal_only_mode = false;
bool is_rom = false; bool is_rom = false;
bool is_ir = false; bool is_ir = false;
@ -174,6 +212,8 @@ i32 main(i32 argc, char *argv[]) {
for (i32 i = 1; i < argc; i++) { for (i32 i = 1; i < argc; i++) {
if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--dump-rom") == 0) { if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--dump-rom") == 0) {
dump_rom = true; dump_rom = true;
} else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--term") == 0) {
terminal_only_mode = true;
} else if (input_file == nil) { } else if (input_file == nil) {
// This is the input file // This is the input file
input_file = argv[i]; input_file = argv[i];
@ -234,6 +274,11 @@ i32 main(i32 argc, char *argv[]) {
vm_register_device(&vm, "/dev/term/0", "terminal", &console_data, vm_register_device(&vm, "/dev/term/0", "terminal", &console_data,
&console_device_ops, 4); &console_device_ops, 4);
if (terminal_only_mode) {
while (step_vm(&vm));
return 0;
}
if (SDL_Init(SDL_INIT_VIDEO) < 0) { if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL initialization failed: %s\n", SDL_GetError()); printf("SDL initialization failed: %s\n", SDL_GetError());
return 1; return 1;
@ -326,6 +371,7 @@ i32 main(i32 argc, char *argv[]) {
i32 cycles_this_frame = 0; i32 cycles_this_frame = 0;
i32 max_cycles_per_frame = 100; // Adjust this value i32 max_cycles_per_frame = 100; // Adjust this value
while (cycles_this_frame < max_cycles_per_frame) { while (cycles_this_frame < max_cycles_per_frame) {
//printf("code[%d] = %s\n", vm.pc, opcode_to_string(vm.code[vm.pc]));
if (!step_vm(&vm)) { if (!step_vm(&vm)) {
running = false; running = false;
break; break;

View File

@ -1,9 +1,12 @@
#include "assembler.h"
#include "../../vm/common.h" #include "../../vm/common.h"
#include "../../vm/fixed.h" #include "../../vm/fixed.h"
#include "../../vm/libc.h" #include "../../vm/libc.h"
#include "../../vm/opcodes.h" #include "../../vm/opcodes.h"
#include "assembler.h"
#include "lexer.h" #include "lexer.h"
/* FIXME: remove these and replace with libc.h instead */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -12,124 +15,123 @@ const char *opcode_to_string(Opcode op) {
static const char *names[] = { static const char *names[] = {
[OP_EXIT] = "exit", [OP_EXIT] = "exit",
[OP_JMP] = "jump", [OP_JMP] = "jump",
[OP_JMPF] = "jump-if-flag", [OP_JMPF] = "jump_if_flag",
[OP_CALL] = "call", [OP_CALL] = "call",
[OP_RETURN] = "return", [OP_RETURN] = "return",
/* Immediate loads (only 32-bit variant needed) */ [OP_LOAD_IMM] = "load_immediate",
[OP_LOAD_IMM] = "load-immediate",
/* Register-indirect loads */ /* Register_indirect loads */
[OP_LOAD_IND_8] = "load-indirect-8", [OP_LOAD_IND_8] = "load_indirect_8",
[OP_LOAD_IND_16] = "load-indirect-16", [OP_LOAD_IND_16] = "load_indirect_16",
[OP_LOAD_IND_32] = "load-indirect-32", [OP_LOAD_IND_32] = "load_indirect_32",
/* Absolute address loads */ /* Absolute address loads */
[OP_LOAD_ABS_8] = "load-absolute-8", [OP_LOAD_ABS_8] = "load_absolute_8",
[OP_LOAD_ABS_16] = "load-absolute-16", [OP_LOAD_ABS_16] = "load_absolute_16",
[OP_LOAD_ABS_32] = "load-absolute-32", [OP_LOAD_ABS_32] = "load_absolute_32",
/* Base+offset loads */ /* Base+offset loads */
[OP_LOAD_OFF_8] = "load-offset-8", [OP_LOAD_OFF_8] = "load_offset_8",
[OP_LOAD_OFF_16] = "load-offset-16", [OP_LOAD_OFF_16] = "load_offset_16",
[OP_LOAD_OFF_32] = "load-offset-32", [OP_LOAD_OFF_32] = "load_offset_32",
/* Absolute address stores */ /* Absolute address stores */
[OP_STORE_ABS_8] = "store-absolute-8", [OP_STORE_ABS_8] = "store_absolute_8",
[OP_STORE_ABS_16] = "store-absolute-16", [OP_STORE_ABS_16] = "store_absolute_16",
[OP_STORE_ABS_32] = "store-absolute-32", [OP_STORE_ABS_32] = "store_absolute_32",
/* Register-indirect stores */ /* Register_indirect stores */
[OP_STORE_IND_8] = "store-indirect-8", [OP_STORE_IND_8] = "store_indirect_8",
[OP_STORE_IND_16] = "store-indirect-16", [OP_STORE_IND_16] = "store_indirect_16",
[OP_STORE_IND_32] = "store-indirect-32", [OP_STORE_IND_32] = "store_indirect_32",
/* Base+offset stores */ /* Base+offset stores */
[OP_STORE_OFF_8] = "store-offset-8", [OP_STORE_OFF_8] = "store_offset_8",
[OP_STORE_OFF_16] = "store-offset-16", [OP_STORE_OFF_16] = "store_offset_16",
[OP_STORE_OFF_32] = "store-offset-32", [OP_STORE_OFF_32] = "store_offset_32",
/* Memory operations */ /* Memory operations */
[OP_MALLOC] = "malloc", [OP_MALLOC] = "malloc",
[OP_MEMSET_8] = "memset-8", [OP_MEMSET_8] = "memset_8",
[OP_MEMSET_16] = "memset-16", [OP_MEMSET_16] = "memset_16",
[OP_MEMSET_32] = "memset-32", [OP_MEMSET_32] = "memset_32",
/* Register operations */ /* Register operations */
[OP_REG_MOV] = "register-move", [OP_REG_MOV] = "register_move",
[OP_SYSCALL] = "syscall", [OP_SYSCALL] = "syscall",
/* Bit operations */ /* Bit operations */
[OP_BIT_SHIFT_LEFT] = "bit-shift-left", [OP_BIT_SHIFT_LEFT] = "bit_shift_left",
[OP_BIT_SHIFT_RIGHT] = "bit-shift-right", [OP_BIT_SHIFT_RIGHT] = "bit_shift_right",
[OP_BIT_SHIFT_R_EXT] = "bit-shift-re", [OP_BIT_SHIFT_R_EXT] = "bit_shift_re",
[OP_BAND] = "bit-and", [OP_BAND] = "bit_and",
[OP_BOR] = "bit-or", [OP_BOR] = "bit_or",
[OP_BXOR] = "bit-xor", [OP_BXOR] = "bit_xor",
/* Integer arithmetic */ /* Integer arithmetic */
[OP_ADD_INT] = "add-int", [OP_ADD_INT] = "add_int",
[OP_SUB_INT] = "sub-int", [OP_SUB_INT] = "sub_int",
[OP_MUL_INT] = "mul-int", [OP_MUL_INT] = "mul_int",
[OP_DIV_INT] = "div-int", [OP_DIV_INT] = "div_int",
/* Natural number arithmetic */ /* Natural number arithmetic */
[OP_ADD_NAT] = "add-nat", [OP_ADD_NAT] = "add_nat",
[OP_SUB_NAT] = "sub-nat", [OP_SUB_NAT] = "sub_nat",
[OP_MUL_NAT] = "mul-nat", [OP_MUL_NAT] = "mul_nat",
[OP_DIV_NAT] = "div-nat", [OP_DIV_NAT] = "div_nat",
/* Floating point operations */ /* Floating point operations */
[OP_ADD_REAL] = "add-real", [OP_ADD_REAL] = "add_real",
[OP_SUB_REAL] = "sub-real", [OP_SUB_REAL] = "sub_real",
[OP_MUL_REAL] = "mul-real", [OP_MUL_REAL] = "mul_real",
[OP_DIV_REAL] = "div-real", [OP_DIV_REAL] = "div_real",
/* Type conversions */ /* Type conversions */
[OP_INT_TO_REAL] = "int-to-real", [OP_INT_TO_REAL] = "int_to_real",
[OP_NAT_TO_REAL] = "nat-to-real", [OP_NAT_TO_REAL] = "nat_to_real",
[OP_REAL_TO_INT] = "real-to-int", [OP_REAL_TO_INT] = "real_to_int",
[OP_REAL_TO_NAT] = "real-to-nat", [OP_REAL_TO_NAT] = "real_to_nat",
/* Integer comparisons */ /* Integer comparisons */
[OP_JEQ_INT] = "jump-eq-int", [OP_JEQ_INT] = "jump_eq_int",
[OP_JNEQ_INT] = "jump-neq-int", [OP_JNEQ_INT] = "jump_neq_int",
[OP_JGT_INT] = "jump-gt-int", [OP_JGT_INT] = "jump_gt_int",
[OP_JLT_INT] = "jump-lt-int", [OP_JLT_INT] = "jump_lt_int",
[OP_JLE_INT] = "jump-le-int", [OP_JLE_INT] = "jump_le_int",
[OP_JGE_INT] = "jump-ge-int", [OP_JGE_INT] = "jump_ge_int",
/* Natural number comparisons */ /* Natural number comparisons */
[OP_JEQ_NAT] = "jump-eq-nat", [OP_JEQ_NAT] = "jump_eq_nat",
[OP_JNEQ_NAT] = "jump-neq-nat", [OP_JNEQ_NAT] = "jump_neq_nat",
[OP_JGT_NAT] = "jump-gt-nat", [OP_JGT_NAT] = "jump_gt_nat",
[OP_JLT_NAT] = "jump-lt-nat", [OP_JLT_NAT] = "jump_lt_nat",
[OP_JLE_NAT] = "jump-le-nat", [OP_JLE_NAT] = "jump_le_nat",
[OP_JGE_NAT] = "jump-ge-nat", [OP_JGE_NAT] = "jump_ge_nat",
/* Floating point comparisons */ /* Floating point comparisons */
[OP_JEQ_REAL] = "jump-eq-real", [OP_JEQ_REAL] = "jump_eq_real",
[OP_JNEQ_REAL] = "jump-neq-real", [OP_JNEQ_REAL] = "jump_neq_real",
[OP_JGE_REAL] = "jump-ge-real", [OP_JGE_REAL] = "jump_ge_real",
[OP_JGT_REAL] = "jump-gt-real", [OP_JGT_REAL] = "jump_gt_real",
[OP_JLT_REAL] = "jump-lt-real", [OP_JLT_REAL] = "jump_lt_real",
[OP_JLE_REAL] = "jump-le-real", [OP_JLE_REAL] = "jump_le_real",
/* String operations */ /* String operations */
[OP_STRLEN] = "string-length", [OP_STRLEN] = "string_length",
[OP_STREQ] = "string-eq", [OP_STREQ] = "string_eq",
[OP_STRCAT] = "string-concat", [OP_STRCAT] = "string_concat",
[OP_STR_GET_CHAR] = "string-get-char", [OP_STR_GET_CHAR] = "string_get_char",
[OP_STR_FIND_CHAR] = "string-find-char", [OP_STR_FIND_CHAR] = "string_find_char",
[OP_STR_SLICE] = "string-slice", [OP_STR_SLICE] = "string_slice",
/* String conversions */ /* String conversions */
[OP_INT_TO_STRING] = "int-to-string", [OP_INT_TO_STRING] = "int_to_string",
[OP_NAT_TO_STRING] = "nat-to-string", [OP_NAT_TO_STRING] = "nat_to_string",
[OP_REAL_TO_STRING] = "real-to-string", [OP_REAL_TO_STRING] = "real_to_string",
[OP_STRING_TO_INT] = "string-to-int", [OP_STRING_TO_INT] = "string_to_int",
[OP_STRING_TO_NAT] = "string-to-nat", [OP_STRING_TO_NAT] = "string_to_nat",
[OP_STRING_TO_REAL] = "string-to-real"}; [OP_STRING_TO_REAL] = "string_to_real"};
if (op < 0 || op >= (int)(sizeof(names) / sizeof(names[0]))) { if (op < 0 || op >= (int)(sizeof(names) / sizeof(names[0]))) {
return "<invalid-opcode>"; return "<invalid-opcode>";
@ -139,27 +141,28 @@ const char *opcode_to_string(Opcode op) {
return name ? name : "<unknown-opcode>"; return name ? name : "<unknown-opcode>";
} }
void emit_op(VM *vm, u8 byte) { void emit_op(VM *vm, u8 byte) {
printf("vm->code[%d] = %s\n", vm->cp, opcode_to_string(byte)); #ifdef DEBUG_PRINT
printf("code[%d] = %s\n", vm->cp, opcode_to_string(byte));
#endif
vm->code[vm->cp] = byte; vm->code[vm->cp] = byte;
} }
void emit_byte(VM *vm, u8 byte) { void emit_byte(VM *vm, u8 byte) {
printf("vm->code[%d] = %d\n", vm->cp, byte); #ifdef DEBUG_PRINT
printf("code[%d] = %d\n", vm->cp, byte);
#endif
vm->code[vm->cp] = byte; vm->code[vm->cp] = byte;
} }
void emit_u32(VM *vm, u32 value) { void emit_u32(VM *vm, u32 value) {
printf("vm->code[%d..%d] = %d\n", vm->cp, vm->cp + 3, value); #ifdef DEBUG_PRINT
printf("code[%d..%d] = %d\n", vm->cp, vm->cp + 3, value);
#endif
write_u32(vm, code, vm->cp, value); write_u32(vm, code, vm->cp, value);
} }
void symbol_table_init(SymbolTable *table) {
table->symbols = calloc(16, sizeof(Symbol));
table->count = 0;
table->capacity = 16;
}
Symbol *symbol_table_lookup(SymbolTable *table, const char *name, u32 length) { Symbol *symbol_table_lookup(SymbolTable *table, const char *name, u32 length) {
for (u32 i = 0; i < table->count; i++) { for (u32 i = 0; i < table->count; i++) {
if (table->symbols[i].name_length == length) { if (table->symbols[i].name_length == length) {
@ -182,19 +185,23 @@ u32 symbol_table_add(SymbolTable *table, Symbol s) {
exit(1); exit(1);
} }
if (table->count >= table->capacity) { if (!resize_or_check_size(table)) {
table->capacity *= 2; fprintf(stderr,
table->symbols = realloc(table->symbols, table->capacity * sizeof(Symbol)); "Error: Symbol table is out of memory! This is likely because you built this in static mode."
"if you built using malloc, that means your computer is out of memory. Close a few tabs in your web browser and try again."
"Count was %d, while capacity was %d\n",
table->count, table->capacity);
exit(1);
} }
#ifdef DEBUG_PRINT
if (s.scope == VAR) { if (s.scope == VAR) {
// ignore for now printf("$%d = %s\n", s.ref, s.name);
// printf("$%d = %s\n", s.ref, s.name);
} else if (s.scope == GLOBAL) { } else if (s.scope == GLOBAL) {
printf("memory[%d] = %s\n", s.ref, s.name); printf("memory[%d] = %s\n", s.ref, s.name);
} else { } else {
printf("code[%d] = %s\n", s.ref, s.name); printf("code[%d] = %s\n", s.ref, s.name);
} }
#endif
table->symbols[table->count] = s; table->symbols[table->count] = s;
u32 index = table->count; u32 index = table->count;
@ -232,7 +239,7 @@ u32 get_ptr(Token token, SymbolTable *st) {
return out; return out;
} }
fprintf(stderr, "Error: Not a register or symbol '%.*s'\n", token.length, fprintf(stderr, "Error: Not a pointer or symbol '%.*s'\n", token.length,
token.start); token.start);
exit(1); exit(1);
} }
@ -595,6 +602,7 @@ void define_branch(VM *vm, SymbolTable *st) {
} }
memcpy(s.name, name.start, name.length); memcpy(s.name, name.start, name.length);
s.name_length = name.length; s.name_length = name.length;
s.name[name.length] = '\0';
s.ref = vm->cp; s.ref = vm->cp;
symbol_table_add(st, s); symbol_table_add(st, s);
@ -625,9 +633,6 @@ int get_instruction_byte_size(const char *opname) {
strcmp(opname, "real_to_nat") == 0 || strcmp(opname, "nat_to_int") == 0 || strcmp(opname, "real_to_nat") == 0 || strcmp(opname, "nat_to_int") == 0 ||
strcmp(opname, "int_to_nat") == 0 || strcmp(opname, "int_to_nat") == 0 ||
strcmp(opname, "string_length") == 0 || strcmp(opname, "string_length") == 0 ||
strcmp(opname, "store_absolute_32") == 0 ||
strcmp(opname, "store_absolute_8") == 0 ||
strcmp(opname, "store_absolute_16") == 0 ||
strcmp(opname, "memset") == 0 || strcmp(opname, "memset") == 0 || strcmp(opname, "memset") == 0 || strcmp(opname, "memset") == 0 ||
strcmp(opname, "memset_8") == 0 || strcmp(opname, "memset_16") == 0 || strcmp(opname, "memset_8") == 0 || strcmp(opname, "memset_16") == 0 ||
strcmp(opname, "register_move") == 0 || strcmp(opname, "malloc") == 0) { strcmp(opname, "register_move") == 0 || strcmp(opname, "malloc") == 0) {
@ -660,7 +665,10 @@ int get_instruction_byte_size(const char *opname) {
strcmp(opname, "load_immediate") == 0 || strcmp(opname, "load_immediate") == 0 ||
strcmp(opname, "load_address") == 0 || strcmp(opname, "load_address") == 0 ||
strcmp(opname, "load_absolute_16") == 0 || strcmp(opname, "load_absolute_16") == 0 ||
strcmp(opname, "load_absolute_8") == 0) { strcmp(opname, "load_absolute_8") == 0 ||
strcmp(opname, "store_absolute_32") == 0 ||
strcmp(opname, "store_absolute_8") == 0 ||
strcmp(opname, "store_absolute_16") == 0) {
return 6; return 6;
} }
@ -696,12 +704,15 @@ int get_instruction_byte_size(const char *opname) {
exit(-1); exit(-1);
} }
#define FAKE_OP(op) \ #define FAKE_OP(op) \
} \ } else if (strleq(token.start, op, token.length)) { \
else if (strleq(token.start, op, token.length)) { \ do { \
while (token.type != TOKEN_SEMICOLON) \ while (token.type != TOKEN_SEMICOLON) { \
token = next_token(); \ token = next_token(); \
vm->cp += get_instruction_byte_size(op); } \
/*printf("code[%d]=%s\n %d + %d = %d\n", vm->cp, op, get_instruction_byte_size(op), vm->cp, vm->cp + get_instruction_byte_size(op)); */\
vm->cp += get_instruction_byte_size(op); \
} while(0);
/** /**
* Build the symbol table and calculate the types/size/offsets of all values. * Build the symbol table and calculate the types/size/offsets of all values.
@ -760,6 +771,9 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
continue; continue;
} }
#ifdef DEBUG_PRINT
printf("-- %.*s --\n", token.length, token.start);
#endif
if (token.type == TOKEN_IDENTIFIER) { if (token.type == TOKEN_IDENTIFIER) {
// check to see if it is an opcode first // check to see if it is an opcode first
if (strleq(token.start, "exit", token.length)) { if (strleq(token.start, "exit", token.length)) {
@ -769,6 +783,10 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
next_token(); next_token();
vm->cp += 4; vm->cp += 4;
#ifdef DEBUG_PRINT
printf("code[%d] = exit\n", vm->cp);
#endif
next_token_is(TOKEN_SEMICOLON); next_token_is(TOKEN_SEMICOLON);
} else if (strleq(token.start, "call", token.length)) { } else if (strleq(token.start, "call", token.length)) {
@ -777,27 +795,27 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
next_token_is(TOKEN_IDENTIFIER); next_token_is(TOKEN_IDENTIFIER);
vm->cp += 4; vm->cp += 4;
bool has_return = false;
u8 arg_count = 0;
vm->cp++; vm->cp++;
Token next = next_token_is(TOKEN_LPAREN);
Token next = next_token(); next = next_token();
while (next.type != TOKEN_SEMICOLON) { while (next.type != TOKEN_RPAREN) {
if (next.type != TOKEN_ARROW_RIGHT) {
get_reg(next, st); get_reg(next, st);
vm->cp++; vm->cp++;
arg_count++; next = next_token();
} else {
has_return = true;
arg_count--; // is a return not an arg
}
next = next_token();
} }
if (!has_return) { next = next_token();
if (next.type == TOKEN_SEMICOLON) {
vm->cp++;
} else {
next = next_token();
get_reg(next, st);
vm->cp++; vm->cp++;
continue;
} }
#ifdef DEBUG_PRINT
printf("code[%d] = call\n", vm->cp);
#endif
continue;
} else if (strleq(token.start, "syscall", token.length)) { } else if (strleq(token.start, "syscall", token.length)) {
vm->cp++; vm->cp++;
@ -807,13 +825,14 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) {
next = next_token(); next = next_token();
while (next.type != TOKEN_SEMICOLON) { while (next.type != TOKEN_SEMICOLON) {
if (next.type != TOKEN_ARROW_RIGHT) { get_reg(next, st);
get_reg(next, st); vm->cp++;
vm->cp++;
}
next = next_token(); next = next_token();
} }
#ifdef DEBUG_PRINT
printf("code[%d] = syscall\n", vm->cp);
#endif
continue;
FAKE_OP("load_immediate") FAKE_OP("load_immediate")
FAKE_OP("load_address") FAKE_OP("load_address")
FAKE_OP("malloc") FAKE_OP("malloc")
@ -982,6 +1001,9 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
continue; continue;
} }
#ifdef DEBUG_PRINT
printf("-- %.*s --\n", token.length, token.start);
#endif
if (token.type == TOKEN_IDENTIFIER) { if (token.type == TOKEN_IDENTIFIER) {
// check to see if it is an opcode first // check to see if it is an opcode first
if (strleq(token.start, "exit", token.length)) { if (strleq(token.start, "exit", token.length)) {
@ -1005,35 +1027,36 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
emit_u32(vm, ptr); emit_u32(vm, ptr);
vm->cp += 4; vm->cp += 4;
bool has_return = false;
u8 arg_count = 0; u8 arg_count = 0;
u32 arg_pos = vm->cp++; u32 arg_pos = vm->cp++;
printf("vm->code[%d] = ?\n", arg_pos); Token next = next_token_is(TOKEN_LPAREN);
next = next_token();
Token next = next_token(); while (next.type != TOKEN_RPAREN) {
while (next.type != TOKEN_SEMICOLON) {
if (next.type != TOKEN_ARROW_RIGHT) {
u8 arg = get_reg(next, st); u8 arg = get_reg(next, st);
emit_byte(vm, arg); emit_byte(vm, arg);
vm->cp++; vm->cp++;
arg_count++; arg_count++;
} else { next = next_token();
has_return = true;
arg_count--; // is a return not an arg
}
next = next_token();
} }
/* patch number of args */
vm->code[arg_pos] = arg_count; vm->code[arg_pos] = arg_count;
printf("^vm->code[%d] = %d\n", arg_pos, arg_count); #ifdef DEBUG_PRINT
printf("^code[%d] = %d\n", arg_pos, arg_count);
#endif
if (!has_return) { next = next_token();
vm->cp++; if (next.type == TOKEN_SEMICOLON) {
emit_byte(vm, 255); emit_byte(vm, 255);
continue; vm->cp++;
} else {
next = next_token();
u8 arg = get_reg(next, st);
emit_byte(vm, arg);
vm->cp++;
} }
continue;
} else if (strleq(token.start, "syscall", token.length)) { } else if (strleq(token.start, "syscall", token.length)) {
emit_op(vm, OP_SYSCALL); emit_op(vm, OP_SYSCALL);
@ -1062,15 +1085,20 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
vm->cp += 4; vm->cp += 4;
next = next_token(); next = next_token();
while (next.type != TOKEN_SEMICOLON) { while (next.type != TOKEN_SEMICOLON && next.type != TOKEN_ARROW_RIGHT) {
if (next.type != TOKEN_ARROW_RIGHT) { u8 arg =get_reg(next, st);
u8 arg = get_reg(next, st); emit_byte(vm, arg);
emit_byte(vm, arg); vm->cp++;
vm->cp++;
}
next = next_token(); next = next_token();
} }
if (next.type == TOKEN_ARROW_RIGHT) {
next = next_token();
u8 arg = get_reg(next, st);
emit_byte(vm, arg);
vm->cp++;
}
} else if (strleq(token.start, "load_immediate", token.length)) { } else if (strleq(token.start, "load_immediate", token.length)) {
emit_op(vm, OP_LOAD_IMM); emit_op(vm, OP_LOAD_IMM);
@ -1168,6 +1196,8 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
emit_byte(vm, arg); emit_byte(vm, arg);
vm->cp++; vm->cp++;
next_token_is(TOKEN_ARROW_RIGHT);
reg = next_token(); reg = next_token();
arg = get_reg(reg, st); arg = get_reg(reg, st);
emit_byte(vm, arg); emit_byte(vm, arg);
@ -1188,6 +1218,8 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
emit_byte(vm, arg); emit_byte(vm, arg);
vm->cp++; vm->cp++;
next_token_is(TOKEN_ARROW_RIGHT);
reg = next_token(); reg = next_token();
arg = get_reg(reg, st); arg = get_reg(reg, st);
emit_byte(vm, arg); emit_byte(vm, arg);
@ -1208,6 +1240,8 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
emit_byte(vm, arg); emit_byte(vm, arg);
vm->cp++; vm->cp++;
next_token_is(TOKEN_ARROW_RIGHT);
reg = next_token(); reg = next_token();
arg = get_reg(reg, st); arg = get_reg(reg, st);
emit_byte(vm, arg); emit_byte(vm, arg);
@ -1444,10 +1478,10 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
next_token_is(TOKEN_ARROW_RIGHT); next_token_is(TOKEN_ARROW_RIGHT);
Token id = next_token(); reg = next_token();
u32 ptr = get_ptr(id, st); arg = get_reg(reg, st);
emit_u32(vm, ptr); emit_byte(vm, arg);
vm->cp += 4; vm->cp++;
next_token_is(TOKEN_SEMICOLON); next_token_is(TOKEN_SEMICOLON);
} else if (strleq(token.start, "store_indirect_16", token.length)) { } else if (strleq(token.start, "store_indirect_16", token.length)) {
@ -1461,10 +1495,10 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
next_token_is(TOKEN_ARROW_RIGHT); next_token_is(TOKEN_ARROW_RIGHT);
Token id = next_token(); reg = next_token();
u32 ptr = get_ptr(id, st); arg = get_reg(reg, st);
emit_u32(vm, ptr); emit_byte(vm, arg);
vm->cp += 4; vm->cp++;
next_token_is(TOKEN_SEMICOLON); next_token_is(TOKEN_SEMICOLON);
} else if (strleq(token.start, "store_indirect_32", token.length)) { } else if (strleq(token.start, "store_indirect_32", token.length)) {
@ -1478,10 +1512,10 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
next_token_is(TOKEN_ARROW_RIGHT); next_token_is(TOKEN_ARROW_RIGHT);
Token id = next_token(); reg = next_token();
u32 ptr = get_ptr(id, st); arg = get_reg(reg, st);
emit_u32(vm, ptr); emit_byte(vm, arg);
vm->cp += 4; vm->cp++;
next_token_is(TOKEN_SEMICOLON); next_token_is(TOKEN_SEMICOLON);
} else if (strleq(token.start, "store_offset_8", token.length)) { } else if (strleq(token.start, "store_offset_8", token.length)) {
@ -2383,11 +2417,8 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) {
/** /**
* Emit bytecode to the VM from the source string. * Emit bytecode to the VM from the source string.
*/ */
void assemble(VM *vm, char *source) { void assemble(VM *vm, SymbolTable *st, char *source) {
SymbolTable st = {0}; build_symbol_table(vm, source, st);
symbol_table_init(&st); vm->cp = 0; /* actually start emitting code */
build_symbol_table(vm, source, &st); emit_bytecode(vm, source, st);
vm->cp = 0; /* actuall start emitting code */
emit_bytecode(vm, source, &st);
free(st.symbols);
} }

View File

@ -43,6 +43,9 @@ struct symbol_tab_s {
u32 capacity; u32 capacity;
}; };
void assemble(VM *vm, char *source); void assemble(VM *vm, SymbolTable *st, char *source);
extern bool resize_or_check_size(SymbolTable *table);/* implement this in arch/ not here */
const char *opcode_to_string(Opcode op);
#endif #endif

View File

@ -103,6 +103,10 @@ struct names_tab_s {
u32 capacity; u32 capacity;
}; };
/**
* FIXME:
* Symbols need to be inside a scope so we can have duplicates
*/
struct symbol_tab_s { struct symbol_tab_s {
Symbol *symbols; Symbol *symbols;
u32 count; u32 count;

View File

@ -349,37 +349,34 @@ bool step_vm(VM *vm) {
} }
case OP_STORE_ABS_32: { case OP_STORE_ABS_32: {
u32 v, ptr; u32 v, ptr;
u8 dest, src1; u8 src1;
src1 = read_u8(vm, code, vm->pc); src1 = read_u8(vm, code, vm->pc);
vm->pc++; vm->pc++;
dest = read_u8(vm, code, vm->pc); ptr = read_u32(vm, code, vm->pc);
vm->pc++; vm->pc += 4;
v = frame->locals[src1]; v = frame->locals[src1];
ptr = frame->locals[dest];
write_u32(vm, memory, ptr, v); write_u32(vm, memory, ptr, v);
return true; return true;
} }
case OP_STORE_ABS_16: { case OP_STORE_ABS_16: {
u32 v, ptr; u32 v, ptr;
u8 dest, src1; u8 src1;
src1 = read_u8(vm, code, vm->pc); src1 = read_u8(vm, code, vm->pc);
vm->pc++; vm->pc++;
dest = read_u8(vm, code, vm->pc); ptr = read_u32(vm, code, vm->pc);
vm->pc++; vm->pc += 4;
v = frame->locals[src1]; v = frame->locals[src1];
ptr = frame->locals[dest];
write_u16(vm, memory, ptr, v); write_u16(vm, memory, ptr, v);
return true; return true;
} }
case OP_STORE_ABS_8: { case OP_STORE_ABS_8: {
u32 v, ptr; u32 v, ptr;
u8 dest, src1; u8 src1;
src1 = read_u8(vm, code, vm->pc); src1 = read_u8(vm, code, vm->pc);
vm->pc++; vm->pc++;
dest = read_u8(vm, code, vm->pc); ptr = read_u32(vm, code, vm->pc);
vm->pc++; vm->pc += 4;
v = frame->locals[src1]; v = frame->locals[src1];
ptr = frame->locals[dest];
write_u8(vm, memory, ptr, v); write_u8(vm, memory, ptr, v);
return true; return true;
} }

View File

@ -1,26 +0,0 @@
((code
(label main
(load-immediate $0 1)
(load-immediate $1 1)
(call &add ($0 $1) $2)
(int-to-string $3 $2)
(call &pln ($3) nil)
(exit 0))
(label add
(add-int $2 $1 $0)
(return $2))
(label pln
(load-immediate $1 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(string-length $2 $0)
(syscall WRITE $1 $0 $2)
(load-immediate $3 &new-line)
(string-length $4 $3)
(syscall WRITE $1 $3 $4)
(return nil)))
(data
(label terminal-namespace "/dev/term/0")
(label new-line "\n")))

BIN
test/add.rom Normal file

Binary file not shown.

View File

@ -6,9 +6,9 @@ global int y = 1;
function main () function main ()
load_absolute_32 x -> $0; load_absolute_32 x -> $0;
load_absolute_32 y -> $1; load_absolute_32 y -> $1;
call add $0 $1 -> $2; call add ($0 $1) -> $2;
int_to_string $2 -> $3; int_to_string $2 -> $3;
call pln $3; call pln ($3);
exit 0; exit 0;
function add (int a $0, int b $1) function add (int a $0, int b $1)
@ -26,7 +26,7 @@ function pln (str message $0)
load_immediate 0 -> mode; load_immediate 0 -> mode;
load_address terminal_namespace -> term_ns; load_address terminal_namespace -> term_ns;
syscall OPEN term_ns mode -> term; syscall OPEN term_ns mode term;
string_length message -> msg_length; string_length message -> msg_length;
syscall WRITE term message msg_length; syscall WRITE term message msg_length;
load_address new_line -> nl; load_address new_line -> nl;

View File

@ -1,33 +0,0 @@
((code
(label main
(load-immediate $0 35)
(call &fib ($0) $0)
(int-to-string $1 $0)
(call &pln ($1) nil)
(exit 0))
(label fib
(load-immediate $1 2)
(jump-lt-int &base-case $0 $1)
(load-immediate $3 2)
(sub-int $4 $0 $3)
(call &fib ($4) $5)
(load-immediate $3 1)
(sub-int $4 $0 $3)
(call &fib ($4) $6)
(add-int $7 $6 $5)
(return $7)
(label base-case
(return $0)))
(label pln
(load-immediate $1 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(load-immediate $3 &new-line)
(string-length $2 $0)
(syscall WRITE $1 $0 $2)
(string-length $4 $3)
(syscall WRITE $1 $3 $4)
(return nil)))
(data
(label terminal-namespace "/dev/term/0")
(label new-line "\n")))

BIN
test/fib.rom Normal file

Binary file not shown.

View File

@ -4,10 +4,10 @@ global str new_line = "\n";
function main () function main ()
int str_n $1; int str_n $1;
load_immediate 36 -> $0; load_immediate 35 -> $0;
call fib $0 -> $0; call fib ($0) -> $0;
int_to_string $0 -> str_n; int_to_string $0 -> str_n;
call pln str_n; call pln (str_n);
exit 0; exit 0;
function fib (int n $0) function fib (int n $0)
@ -17,11 +17,11 @@ function fib (int n $0)
load_immediate 2 -> $3; load_immediate 2 -> $3;
sub_int n $3 -> $4; sub_int n $3 -> $4;
call fib $4 -> $5; call fib ($4) -> $5;
load_immediate 1 -> $3; load_immediate 1 -> $3;
sub_int n $3 -> $4; sub_int n $3 -> $4;
call fib $4 -> $6; call fib ($4) -> $6;
add_int $6 $5 -> $7; add_int $6 $5 -> $7;
return $7; return $7;
@ -39,7 +39,7 @@ function pln (str message $0)
load_immediate 0 -> mode; load_immediate 0 -> mode;
load_address terminal_namespace -> term_ns; load_address terminal_namespace -> term_ns;
syscall OPEN term_ns mode -> term; syscall OPEN term_ns mode term;
string_length message -> msg_length; string_length message -> msg_length;
syscall WRITE term message msg_length; syscall WRITE term message msg_length;
load_address new_line -> nl; load_address new_line -> nl;

View File

@ -1,19 +0,0 @@
((code
(label main
(load-immediate $1 &hello-str) ; load hello string ptr
(call &pln ($1) nil)
(exit 0)) ; done
(label pln
(load-immediate $1 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(load-immediate $3 &new-line)
(string-length $2 $0)
(syscall WRITE $1 $0 $2)
(string-length $4 $3)
(syscall WRITE $1 $3 $4)
(return nil)))
(data
(label terminal-namespace "/dev/term/0")
(label new-line "\n")
(label hello-str "nuqneH 'u'?")))

BIN
test/hello.rom Normal file

Binary file not shown.

View File

@ -6,7 +6,7 @@ function main ()
str msg $0; str msg $0;
load_address hello -> msg; load_address hello -> msg;
call pln msg; call pln (msg);
exit 0; exit 0;
function pln (str message $0) function pln (str message $0)
@ -19,7 +19,7 @@ function pln (str message $0)
load_immediate 0 -> mode; load_immediate 0 -> mode;
load_address terminal_namespace -> term_ns; load_address terminal_namespace -> term_ns;
syscall OPEN term_ns mode -> term; syscall OPEN term_ns mode term;
string_length message -> msg_length; string_length message -> msg_length;
syscall WRITE term message msg_length; syscall WRITE term message msg_length;
load_address new_line -> nl; load_address new_line -> nl;

View File

@ -1,44 +0,0 @@
((code
(label main
(load-immediate $0 5.0)
(load-immediate $1 5000)
(load-immediate $2 0)
(load-immediate $3 -1)
(load-immediate $5 5.0)
(label loop-body
(add-real $0 $0 $5)
(add-int $1 $1 $3)
(jump-ge-int &loop-body $1 $2))
(load-immediate $10 &terminal-namespace)
(load-immediate $11 0)
(syscall OPEN $10 $10 $11) ; Terminal term = open(namespace, flags)
(real-to-nat $1 $0)
(load-immediate $7 &prompt)
(string-length $8 $7)
(syscall WRITE $10 $7 $8) ; print prompt
(load-immediate $8 32)
(malloc $11 $8)
(syscall READ $10 $11 $8) ; read in max 32 byte string
(call &pln ($11) nil)
(nat-to-string $4 $1)
(call &pln ($4) nil)
(real-to-string $3 $0)
(call &pln ($3) nil)
(exit 0))
(label pln
(load-immediate $1 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(load-immediate $3 &new-line)
(string-length $2 $0)
(syscall WRITE $1 $0 $2)
(string-length $4 $3)
(syscall WRITE $1 $3 $4)
(return nil)))
(data
(label terminal-namespace "/dev/term/0")
(label prompt "Enter a string: ")
(label new-line "\n")))

BIN
test/loop.rom Normal file

Binary file not shown.

View File

@ -20,7 +20,7 @@ function main ()
load_address terminal_namespace -> in_term; load_address terminal_namespace -> in_term;
load_immediate 0 -> in_mode; load_immediate 0 -> in_mode;
syscall OPEN in_term in_mode -> in_term; // Terminal term = open("/dev/term/0", 0); syscall OPEN in_term in_mode in_term; // Terminal term = open("/dev/term/0", 0);
nat b $1; nat b $1;
real_to_nat a -> b; real_to_nat a -> b;
@ -33,11 +33,11 @@ function main ()
malloc $8 -> user_string; malloc $8 -> user_string;
syscall READ in_term user_string $8; // read in max 32 byte string syscall READ in_term user_string $8; // read in max 32 byte string
call pln user_string; call pln (user_string);
nat_to_string b -> $4; nat_to_string b -> $4;
call pln $4; call pln ($4);
real_to_string a -> $3; real_to_string a -> $3;
call pln $3; call pln ($3);
exit 0; exit 0;
function pln (str message $0) function pln (str message $0)
@ -49,7 +49,7 @@ function pln (str message $0)
load_address terminal_namespace -> term; load_address terminal_namespace -> term;
load_immediate 0 -> mode; load_immediate 0 -> mode;
syscall OPEN term mode -> term; // Terminal term = open("/dev/term/0", 0); syscall OPEN term mode term; // Terminal term = open("/dev/term/0", 0);
string_length message -> msg_length; string_length message -> msg_length;
syscall WRITE term message msg_length; syscall WRITE term message msg_length;
load_address new_line -> nl; load_address new_line -> nl;

View File

@ -1,26 +0,0 @@
((code
(label main
(load-immediate $0 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $0 $0 $11)
(load-immediate $1 &help) ; print help message
(call &pln ($0 $1) nil)
(load-immediate $1 32) ; read in a string of max 32 char length
(malloc $4 $1) ; allocate memory for the string
(syscall READ $0 $4 $1) ; read the string
(call &pln ($0 $4) nil) ; print the string
(exit 0))
(label pln
(load-immediate $3 &new-line)
(string-length $2 $1)
(syscall WRITE $0 $1 $2)
(string-length $4 $3)
(syscall WRITE $0 $3 $4)
(return nil)))
(data
(label terminal-namespace "/dev/term/0")
(label help "Enter a string: ")
(label new-line "\n")))

BIN
test/malloc.rom Normal file

Binary file not shown.

View File

@ -8,7 +8,7 @@ function main ()
load_address terminal_namespace -> in_term; load_address terminal_namespace -> in_term;
load_immediate 0 -> in_mode; load_immediate 0 -> in_mode;
syscall OPEN in_term in_mode -> in_term; // Terminal term = open("/dev/term/0", 0); syscall OPEN in_term in_mode in_term; // Terminal term = open("/dev/term/0", 0);
load_address prompt -> $7; load_address prompt -> $7;
string_length $7 -> $8; string_length $7 -> $8;
@ -19,7 +19,7 @@ function main ()
malloc $8 -> user_string; malloc $8 -> user_string;
syscall READ in_term user_string $8; // read in max 32 byte string syscall READ in_term user_string $8; // read in max 32 byte string
call pln user_string; call pln (user_string);
exit 0; exit 0;
function pln (str message $0) function pln (str message $0)
@ -32,10 +32,11 @@ function pln (str message $0)
load_immediate 0 -> mode; load_immediate 0 -> mode;
load_address terminal_namespace -> term_ns; load_address terminal_namespace -> term_ns;
syscall OPEN term_ns mode -> term; syscall OPEN term_ns mode term;
string_length message -> msg_length; string_length message -> msg_length;
syscall WRITE term message msg_length; syscall WRITE term message msg_length;
load_address new_line -> nl; load_address new_line -> nl;
string_length nl -> nl_length; string_length nl -> nl_length;
syscall WRITE term nl nl_length; syscall WRITE term nl nl_length;
return; return;

View File

@ -1,147 +0,0 @@
((code
(label main
; Open screen
; use load immediate because it is a pointer to a string, not a value
(load-immediate $0 &screen-namespace)
(load-immediate $11 0)
(syscall OPEN $0 $18 $11) ; open(out Plex screen, in namespace, in flags)
(load-offset-32 $20 $0 8) ; load width
(load-offset-32 $22 $0 12) ; load size
(load-immediate $1 16) ; offset for screen buffer
(add-nat $21 $0 $1)
; open mouse
(load-immediate $16 &mouse-namespace)
(syscall OPEN $15 $16 $11) ; open(out Plex mouse, in namespace, in flags)
; outline_swatch(screen, BLACK, 1, 1);
(load-absolute-32 $1 &BLACK)
(load-immediate $12 1)
(load-immediate $13 1)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
; outline_swatch(screen, WHITE, 1, 1);
(load-absolute-32 $1 &WHITE)
(load-immediate $12 21)
(load-immediate $13 1)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
; screen.draw();
(syscall WRITE $0 $21 $22)
(label draw-loop
; load mouse click data
(syscall REFRESH $15)
(load-offset-8 $9 $15 16) ; load btn1 pressed
(jump-eq-nat &draw-loop $9 $11)
(load-offset-32 $7 $15 8) ; load x
(load-offset-32 $8 $15 12) ; load y
(load-immediate $14 20) ; box size
; first row
(load-absolute-32 $1 &BLACK)
(load-immediate $12 1)
(load-immediate $13 1)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &WHITE)
(load-immediate $12 21)
(load-immediate $13 1)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(syscall WRITE $0 $21 $22)
(load-absolute-32 $22 &SELECTED-COLOR) ; color
(load-immediate $1 5) ; size of brush
(call &draw-box ($21 $20 $22 $7 $8 $1 $1) nil)
(jump &draw-loop))
; Flush and exit
(exit 0))
(label set-color-if-clicked
; (click_x, click_y, box_x, box_y, color, box_size)
; Compute right = box_x + box_size
(add-int $6 $2 $5) ; $6 = right edge
; Compute bottom = box_y + box_size
(add-int $7 $3 $5) ; $7 = bottom edge
; Bounds check: x in [box_x, right] and y in [box_y, bottom]
(jump-lt-int &fail $0 $2)
(jump-gt-int &fail $0 $6)
(jump-lt-int &fail $1 $3)
(jump-gt-int &fail $1 $7)
(load-immediate $10 &SELECTED-COLOR)
(store-absolute-8 $10 $4)
(label fail)
(return nil))
(label draw-outlined-swatch
; (base, color, x, y, width)
; Constants
(load-absolute-32 $5 &GRAY)
(load-absolute-32 $10 &SELECTED-COLOR)
(jump-eq-int &set-selected $10 $1)
(jump-eq-int &end-set-selected $5 $5)
(label set-selected)
(load-absolute-32 $5 &DARK-GRAY)
(label end-set-selected)
(load-immediate $6 20) ; outline size
(load-immediate $7 17) ; fill size
(load-immediate $8 2) ; offset
(call &draw-box ($0 $4 $5 $2 $3 $6 $6) nil)
(add-int $9 $2 $8) ; x + 2
(add-int $10 $3 $8) ; y + 2
(call &draw-box ($0 $4 $1 $9 $10 $7 $7) nil)
(return nil))
(label draw-box
; (base, screen_width, color, x_start, y_start, width, height)
; Compute start address: base + y*640 + x
(mul-int $15 $4 $1) ; $15 = y * 640
(add-int $15 $15 $3) ; $15 += x
(add-nat $15 $0 $15) ; $15 = base + pixel_offset
(load-immediate $25 4)
(add-nat $15 $15 $25) ; need to add offset for fat pointer size
; Outer loop: height times
(load-immediate $30 1) ; increment
(label draw-box-outer
(add-int $27 $15 $5) ; $27 = row end = current + width
(register-move $29 $15) ; $7 = pixel pointer
(memset-8 $29 $2 $5) ; draw row
(add-int $15 $15 $1) ; next row (+= 640)
(sub-int $6 $6 $30) ; decrement row count
(jump-gt-int &draw-box-outer $6 0))
(return nil)))
(data
(label screen-namespace "/dev/screen/0")
(label mouse-namespace "/dev/mouse/0")
(label SELECTED-COLOR 255)
(label BLACK 0)
(label WHITE 255)
(label DARK-GRAY 73)
(label GRAY 146)
(label LIGHT-GRAY 182)))

BIN
test/paint-bw.rom Normal file

Binary file not shown.

View File

@ -1,10 +1,10 @@
global const str screen_namespace = "/dev/screen/0"; global str screen_namespace = "/dev/screen/0";
global const str mouse_namespace = "/dev/mouse/0"; global str mouse_namespace = "/dev/mouse/0";
global const byte BLACK = 0; global byte BLACK = 0;
global const byte WHITE = 255; global byte WHITE = 255;
global const byte DARK_GRAY = 73; global byte DARK_GRAY = 73;
global const byte GRAY = 146; global byte GRAY = 146;
global const byte LIGHT_GRAY = 182; global byte LIGHT_GRAY = 182;
global byte SELECTED_COLOR = 255; global byte SELECTED_COLOR = 255;
function main () function main ()
@ -17,7 +17,7 @@ function main ()
// use load immediate because it a pointer to a string, not a value // use load immediate because it a pointer to a string, not a value
load_address screen_namespace -> screen_name; load_address screen_namespace -> screen_name;
load_immediate 0 -> mode; load_immediate 0 -> mode;
syscall OPEN screen_name mode -> screen; // Screen screen = open("/dev/screen/0", 0); syscall OPEN screen_name mode screen; // Screen screen = open("/dev/screen/0", 0);
nat width $20; nat width $20;
nat size $22; nat size $22;
@ -30,26 +30,26 @@ function main ()
plex mouse $15; plex mouse $15;
str mouse_name $16; str mouse_name $16;
load_address mouse_namespace -> mouse_name; load_address mouse_namespace -> mouse_name;
syscall OPEN mouse_name mode -> mouse; // Mouse mouse = open("/dev/mouse/0", 0); syscall OPEN mouse_name mode mouse; // Mouse mouse = open("/dev/mouse/0", 0);
byte color $1; byte color $1;
nat x_pos $12; nat x_pos $12;
nat y_pos $13; nat y_pos $13;
load_absolute_32 BLACK -> color; load_absolute_8 BLACK -> color;
load_immediate 1 -> x_pos; load_immediate 1 -> x_pos;
load_immediate 1 -> y_pos; load_immediate 1 -> y_pos;
call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void; call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_32 WHITE -> color; load_absolute_8 WHITE -> color;
load_immediate 21 -> x_pos; load_immediate 21 -> x_pos;
load_immediate 1 -> y_pos; load_immediate 1 -> y_pos;
call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void; call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
// screen.draw // screen.draw
syscall WRITE screen screen_buffer size; syscall WRITE screen screen_buffer size;
nat zero $11; nat m_zero $11;
loop draw_loop loop draw_loop
// load mouse click data // load mouse click data
@ -58,7 +58,7 @@ function main ()
byte left_down $9; byte left_down $9;
load_offset_8 mouse 16 -> left_down; // load btn1 pressed load_offset_8 mouse 16 -> left_down; // load btn1 pressed
jump_eq_nat draw_loop left_down zero; jump_eq_nat draw_loop left_down m_zero;
nat mouse_x $7; nat mouse_x $7;
nat mouse_y $8; nat mouse_y $8;
@ -69,28 +69,28 @@ function main ()
load_immediate 20 -> box_size; load_immediate 20 -> box_size;
// first row // first row
load_absolute_32 BLACK -> color; load_absolute_8 BLACK -> color;
load_immediate 1 -> x_pos; load_immediate 1 -> x_pos;
load_immediate 1 -> y_pos; load_immediate 1 -> y_pos;
call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void; call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void; call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_32 WHITE -> color; load_absolute_8 WHITE -> color;
load_immediate 21 -> x_pos; load_immediate 21 -> x_pos;
load_immediate 1 -> y_pos; load_immediate 1 -> y_pos;
call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void; call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void; call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
syscall WRITE screen screen_buffer size; syscall WRITE screen screen_buffer size;
byte selected_color $25; byte selected_color $25;
load_absolute_32 SELECTED_COLOR -> selected_color; load_absolute_8 SELECTED_COLOR -> selected_color;
nat brush_size $19; nat brush_size $19;
load_immediate 5 -> brush_size; load_immediate 5 -> brush_size;
call draw_box screen_buffer width selected_color mouse_x mouse_y brush_size brush_size -> void; call draw_box (screen_buffer width selected_color mouse_x mouse_y brush_size brush_size);
jump draw_loop; jump draw_loop;
@ -98,41 +98,41 @@ function main ()
exit 0; exit 0;
function set_color_if_clicked (int click_x $0, int click_y $1, function set_color_if_clicked (int click_x $0, int click_y $1,
int box_x $2, int box_y $3, byte color $4, int box_size $5) int box_x $2, int box_y $3, byte check_color $4, int bsize $5)
// Compute right // Compute right
int right_edge $6; int right_edge $6;
add_int box_x box_size -> right_edge; add_int box_x bsize -> right_edge;
// Compute bottom = box_y + box_size // Compute bottom = box_y + bsize
int bottom_edge $7; int bottom_edge $7;
add_int box_y box_size -> bottom_edge; add_int box_y bsize -> bottom_edge;
// Bounds check: x in [box_x, right] and y in [box_y, bottom] // Bounds check: x in [box_x, right] and y in [box_y, bottom]
jump_lt_int fail click_x box_x; jump_lt_int fail click_x box_x;
jump_ge_int fail click_x right_edge; jump_gt_int fail click_x right_edge;
jump_lt_int fail click_y box_y; jump_lt_int fail click_y box_y;
jump_ge_int fail click_y bottom_edge; jump_gt_int fail click_y bottom_edge;
store_absolute_8 SELECTED_COLOR color; store_absolute_8 check_color -> SELECTED_COLOR;
else fail else fail
return; return;
function draw_outlined_swatch(nat base $0, function draw_outlined_swatch(nat dos_base $0,
byte color $1, int x $2, int y $3, int width $4) byte swatch_color $1, int x $2, int y $3, int dos_width $4)
// Constants // Constants
nat background_color $5; nat background_color $5;
load_absolute_32 GRAY -> background_color; load_absolute_8 GRAY -> background_color;
byte selected_color $10; byte dos_selected_color $10;
load_absolute_32 SELECTED_COLOR -> selected_color; load_absolute_8 SELECTED_COLOR -> dos_selected_color;
jump_eq_int set_selected selected_color color; jump_eq_int set_selected swatch_color dos_selected_color;
jump end_set_selected; jump end_set_selected;
do set_selected do set_selected
load_absolute_32 DARK_GRAY -> background_color; load_absolute_8 DARK_GRAY -> background_color;
else end_set_selected else end_set_selected
nat outline_size $6; nat outline_size $6;
@ -141,27 +141,27 @@ function draw_outlined_swatch(nat base $0,
nat fill_size $7; nat fill_size $7;
load_immediate 17 -> fill_size; load_immediate 17 -> fill_size;
nat offset $8; nat dos_offset $8;
load_immediate 2 -> offset; load_immediate 2 -> dos_offset;
call draw_box base width background_color x y outline_size outline_size -> void; call draw_box (dos_base dos_width background_color x y outline_size outline_size);
add_int x offset -> $9; // x + 2 add_int x dos_offset -> $9; // x + 2
add_int y offset -> $10; // y + 2 add_int y dos_offset -> $10; // y + 2
call draw_box base width color $9 $10 fill_size fill_size -> void; call draw_box (dos_base dos_width swatch_color $9 $10 fill_size fill_size);
return; return;
function draw_box (nat base $0, nat screen_width $1, function draw_box (nat db_base $0, nat screen_width $1,
byte color $2, nat x_start $3, nat y_start $4, byte box_color $2, nat x_start $3, nat y_start $4,
nat width $5, nat height $6) nat db_width $5, nat height $6)
// Compute start address: base + y*640 + x // Compute start address: base + y*640 + x
nat offset $15; nat offset $15;
mul_int y_start screen_width -> offset; mul_int y_start screen_width -> offset;
add_int offset x_start -> offset; add_int offset x_start -> offset;
add_nat offset base -> offset; add_nat offset db_base -> offset;
nat fat_ptr_size $25; nat fat_ptr_size $25;
load_immediate 4 -> fat_ptr_size; load_immediate 4 -> fat_ptr_size;
add_nat offset fat_ptr_size -> offset; // need to add offset for fat pointer size add_nat offset fat_ptr_size -> offset; // need to add offset for fat pointer size
@ -172,13 +172,8 @@ function draw_box (nat base $0, nat screen_width $1,
int zero $26; int zero $26;
load_immediate 0 -> zero; load_immediate 0 -> zero;
int row_end $27;
nat pixel_ptr $29;
loop draw_box_outer loop draw_box_outer
add_int offset width -> row_end; // current + width memset_8 box_color db_width -> offset; // draw row
register_move offset -> pixel_ptr; // set pixel point
memset_8 pixel_ptr color width; // draw row
add_int offset screen_width -> offset; // next row += 640 add_int offset screen_width -> offset; // next row += 640
sub_int height i -> height; // decrement row count sub_int height i -> height; // decrement row count
jump_gt_int draw_box_outer height zero; jump_gt_int draw_box_outer height zero;

View File

@ -1,261 +0,0 @@
((code
(label main
; Open screen
; use load immediate because it is a pointer to a string, not a value
(load-immediate $0 &screen-namespace)
(load-immediate $11 0)
(syscall OPEN $0 $0 $11) ; Screen screen = open(namespace, flags)
(load-offset-32 $20 $0 8) ; load width
(load-offset-32 $22 $0 12) ; load size
(load-immediate $1 16) ; pointer offset for screen buffer
(add-nat $21 $0 $1)
; open mouse
(load-immediate $16 &mouse-namespace)
(syscall OPEN $15 $16 $11) ; Mouse mouse = open(namespace, flags)
; outline_swatch(screen, BLACK, 1, 1);
(load-absolute-32 $1 &BLACK)
(load-immediate $12 1)
(load-immediate $13 1)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
; outline_swatch(screen, WHITE, 1, 1);
(load-absolute-32 $1 &WHITE)
(load-immediate $12 21)
(load-immediate $13 1)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(load-absolute-32 $1 &CHARCOAL)
(load-immediate $12 1)
(load-immediate $13 21)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(load-absolute-32 $1 &DARK-GRAY)
(load-immediate $12 21)
(load-immediate $13 21)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(load-absolute-32 $1 &RED)
(load-immediate $12 1)
(load-immediate $13 41)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(load-absolute-32 $1 &ORANGE)
(load-immediate $12 21)
(load-immediate $13 41)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(load-absolute-32 $1 &YELLOW)
(load-immediate $12 1)
(load-immediate $13 61)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(load-absolute-32 $1 &GREEN)
(load-immediate $12 21)
(load-immediate $13 61)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(load-absolute-32 $1 &BLUE)
(load-immediate $12 1)
(load-immediate $13 81)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(load-absolute-32 $1 &PURPLE)
(load-immediate $12 21)
(load-immediate $13 81)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
; screen.draw();
(syscall WRITE $0 $21 $22)
(label draw-loop
; load mouse click data
(syscall REFRESH $15)
(load-offset-8 $9 $15 16) ; load btn1 pressed
(jump-eq-nat &draw-loop $9 $11)
(load-offset-32 $7 $15 8) ; load x
(load-offset-32 $8 $15 12) ; load y
(load-immediate $14 20) ; box size
; outline_swatch(screen, BLACK, 1, 1);
(load-absolute-32 $1 &BLACK)
(load-immediate $12 1)
(load-immediate $13 1)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
; outline_swatch(screen, WHITE, 1, 1);
(load-absolute-32 $1 &WHITE)
(load-immediate $12 21)
(load-immediate $13 1)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &CHARCOAL)
(load-immediate $12 1)
(load-immediate $13 21)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &DARK-GRAY)
(load-immediate $12 21)
(load-immediate $13 21)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &RED)
(load-immediate $12 1)
(load-immediate $13 41)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &ORANGE)
(load-immediate $12 21)
(load-immediate $13 41)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &YELLOW)
(load-immediate $12 1)
(load-immediate $13 61)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &GREEN)
(load-immediate $12 21)
(load-immediate $13 61)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &BLUE)
(load-immediate $12 1)
(load-immediate $13 81)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(load-absolute-32 $1 &PURPLE)
(load-immediate $12 21)
(load-immediate $13 81)
(call &draw-outlined-swatch ($21 $1 $12 $13 $20) nil)
(call &set-color-if-clicked ($7 $8 $12 $13 $1 $14) nil)
(syscall WRITE $0 $21 $22)
(load-absolute-32 $22 &SELECTED-COLOR) ; color
(load-immediate $1 5) ; size of brush
(call &draw-box ($21 $20 $22 $7 $8 $1 $1) nil)
(jump &draw-loop))
; Flush and exit
(exit 0))
(label set-color-if-clicked
; (click_x, click_y, box_x, box_y, color, box_size)
; Compute right = box_x + box_size
(add-int $6 $2 $5) ; $6 = right edge
; Compute bottom = box_y + box_size
(add-int $7 $3 $5) ; $7 = bottom edge
; Bounds check: x in [box_x, right] and y in [box_y, bottom]
(jump-lt-int &fail $0 $2)
(jump-gt-int &fail $0 $6)
(jump-lt-int &fail $1 $3)
(jump-gt-int &fail $1 $7)
(load-immediate $10 &SELECTED-COLOR)
(store-absolute-8 $10 $4)
(label fail)
(return nil))
(label draw-outlined-swatch
; (base, color, x, y, width)
; Constants
(load-absolute-32 $5 &GRAY)
(load-absolute-32 $10 &SELECTED-COLOR)
(jump-eq-int &set-selected $10 $1)
(jump-eq-int &end-set-selected $5 $5)
(label set-selected)
(load-absolute-32 $5 &DARK-GRAY)
(label end-set-selected)
(load-immediate $6 20) ; outline size
(load-immediate $7 17) ; fill size
(load-immediate $8 2) ; offset
(call &draw-box ($0 $4 $5 $2 $3 $6 $6) nil)
(add-int $9 $2 $8) ; x + 2
(add-int $10 $3 $8) ; y + 2
(call &draw-box ($0 $4 $1 $9 $10 $7 $7) nil)
(return nil))
(label draw-box
; (base, screen_width, color, x_start, y_start, width, height)
; Compute start address: base + y*640 + x
(mul-int $15 $4 $1) ; $15 = y * 640
(add-int $15 $15 $3) ; $15 += x
(add-nat $15 $0 $15) ; $15 = base + pixel_offset
(load-immediate $25 4)
(add-nat $15 $15 $25) ; need to add offset for fat pointer size
; Outer loop: height times
(load-immediate $30 1) ; increment
(label draw-box-outer
(add-int $27 $15 $5) ; $27 = row end = current + width
(register-move $29 $15) ; $7 = pixel pointer
(memset-8 $29 $2 $5) ; draw row
(add-int $15 $15 $1) ; next row (+= 640)
(sub-int $6 $6 $30) ; decrement row count
(jump-gt-int &draw-box-outer $6 0))
(return nil)))
(data
(label screen-namespace "/dev/screen/0")
(label mouse-namespace "/dev/mouse/0")
(label SELECTED-COLOR 255)
(label BLACK 0)
(label WHITE 255)
(label CHARCOAL 36)
(label DARK-GRAY 73)
(label GRAY 146)
(label LIGHT-GRAY 182)
(label DARK-RED 128)
(label RED 224)
(label DARK-YELLOW 144)
(label YELLOW 252)
(label DARK-TEAL 9)
(label TEAL 18)
(label DARK-GREEN 12)
(label GREEN 16)
(label LIME 28)
(label LIGHT-CYAN 159)
(label NAVY 2)
(label BLUE 3)
(label DEEP-SKY-BLUE 10)
(label LIGHT-BLUE 19)
(label PURPLE 131)
(label LIGHT-PURPLE 147)
(label DARK-MAGENTA 130)
(label MAGENTA 227)
(label PLUM 129)
(label PINK 226)
(label SADDLE-BROWN 72)
(label PERU 141)
(label SIENNA 136)
(label ORANGE 241)
(label DARK-ORANGE 208)
(label GOLD 244)))

BIN
test/paint.rom Normal file

Binary file not shown.

View File

@ -5,6 +5,33 @@ global byte WHITE = 255;
global byte DARK_GRAY = 73; global byte DARK_GRAY = 73;
global byte GRAY = 146; global byte GRAY = 146;
global byte LIGHT_GRAY = 182; global byte LIGHT_GRAY = 182;
global byte CHARCOAL = 36;
global byte DARK_RED = 128;
global byte RED = 224;
global byte DARK_YELLOW = 144;
global byte YELLOW = 252;
global byte DARK_TEAL = 9;
global byte TEAL = 18;
global byte DARK_GREEN = 12;
global byte GREEN = 16;
global byte LIME = 28;
global byte LIGHT_CYAN = 159;
global byte NAVY = 2;
global byte BLUE = 3;
global byte DEEP_SKY_BLUE = 10;
global byte LIGHT_BLUE = 19;
global byte PURPLE = 131;
global byte LIGHT_PURPLE = 147;
global byte DARK_MAGENTA = 130;
global byte MAGENTA = 227;
global byte PLUM = 129;
global byte PINK = 226;
global byte SADDLE_BROWN = 72;
global byte PERU = 141;
global byte SIENNA = 136;
global byte ORANGE = 241;
global byte DARK_ORANGE = 208;
global byte GOLD = 244;
global byte SELECTED_COLOR = 255; global byte SELECTED_COLOR = 255;
function main () function main ()
@ -17,7 +44,7 @@ function main ()
// use load immediate because it a pointer to a string, not a value // use load immediate because it a pointer to a string, not a value
load_address screen_namespace -> screen_name; load_address screen_namespace -> screen_name;
load_immediate 0 -> mode; load_immediate 0 -> mode;
syscall OPEN screen_name mode -> screen; // Screen screen = open("/dev/screen/0", 0); syscall OPEN screen_name mode screen; // Screen screen = open("/dev/screen/0", 0);
nat width $20; nat width $20;
nat size $22; nat size $22;
@ -30,26 +57,66 @@ function main ()
plex mouse $15; plex mouse $15;
str mouse_name $16; str mouse_name $16;
load_address mouse_namespace -> mouse_name; load_address mouse_namespace -> mouse_name;
syscall OPEN mouse_name mode -> mouse; // Mouse mouse = open("/dev/mouse/0", 0); syscall OPEN mouse_name mode mouse; // Mouse mouse = open("/dev/mouse/0", 0);
byte color $1; byte color $1;
nat x_pos $12; nat x_pos $12;
nat y_pos $13; nat y_pos $13;
load_absolute_32 BLACK -> color; load_absolute_8 BLACK -> color;
load_immediate 1 -> x_pos; load_immediate 1 -> x_pos;
load_immediate 1 -> y_pos; load_immediate 1 -> y_pos;
call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void; call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_32 WHITE -> color; load_absolute_8 WHITE -> color;
load_immediate 21 -> x_pos; load_immediate 21 -> x_pos;
load_immediate 1 -> y_pos; load_immediate 1 -> y_pos;
call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void; call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 CHARCOAL -> color;
load_immediate 1 -> x_pos;
load_immediate 21 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 DARK_GRAY -> color;
load_immediate 21 -> x_pos;
load_immediate 21 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 RED -> color;
load_immediate 1 -> x_pos;
load_immediate 41 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 ORANGE -> color;
load_immediate 21 -> x_pos;
load_immediate 41 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 YELLOW -> color;
load_immediate 1 -> x_pos;
load_immediate 61 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 GREEN -> color;
load_immediate 21 -> x_pos;
load_immediate 61 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 BLUE -> color;
load_immediate 1 -> x_pos;
load_immediate 81 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
load_absolute_8 PURPLE -> color;
load_immediate 21 -> x_pos;
load_immediate 81 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
// screen.draw // screen.draw
syscall WRITE screen screen_buffer size; syscall WRITE screen screen_buffer size;
nat zero $11; nat m_zero $11;
loop draw_loop loop draw_loop
// load mouse click data // load mouse click data
@ -58,7 +125,7 @@ function main ()
byte left_down $9; byte left_down $9;
load_offset_8 mouse 16 -> left_down; // load btn1 pressed load_offset_8 mouse 16 -> left_down; // load btn1 pressed
jump_eq_nat draw_loop left_down zero; jump_eq_nat draw_loop left_down m_zero;
nat mouse_x $7; nat mouse_x $7;
nat mouse_y $8; nat mouse_y $8;
@ -69,28 +136,75 @@ function main ()
load_immediate 20 -> box_size; load_immediate 20 -> box_size;
// first row // first row
load_absolute_32 BLACK -> color; load_absolute_8 BLACK -> color;
load_immediate 1 -> x_pos; load_immediate 1 -> x_pos;
load_immediate 1 -> y_pos; load_immediate 1 -> y_pos;
call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void; call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void; call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 WHITE -> color;
load_absolute_32 WHITE -> color;
load_immediate 21 -> x_pos; load_immediate 21 -> x_pos;
load_immediate 1 -> y_pos; load_immediate 1 -> y_pos;
call draw_outlined_swatch screen_buffer color x_pos y_pos width -> void; call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked mouse_x mouse_y x_pos y_pos color box_size -> void; call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 CHARCOAL -> color;
load_immediate 1 -> x_pos;
load_immediate 21 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 DARK_GRAY -> color;
load_immediate 21 -> x_pos;
load_immediate 21 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 RED -> color;
load_immediate 1 -> x_pos;
load_immediate 41 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 ORANGE -> color;
load_immediate 21 -> x_pos;
load_immediate 41 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 YELLOW -> color;
load_immediate 1 -> x_pos;
load_immediate 61 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 GREEN -> color;
load_immediate 21 -> x_pos;
load_immediate 61 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 BLUE -> color;
load_immediate 1 -> x_pos;
load_immediate 81 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
load_absolute_8 PURPLE -> color;
load_immediate 21 -> x_pos;
load_immediate 81 -> y_pos;
call draw_outlined_swatch (screen_buffer color x_pos y_pos width);
call set_color_if_clicked (mouse_x mouse_y x_pos y_pos color box_size);
syscall WRITE screen screen_buffer size; syscall WRITE screen screen_buffer size;
byte selected_color $25; byte selected_color $25;
load_absolute_32 SELECTED_COLOR -> selected_color; load_absolute_8 SELECTED_COLOR -> selected_color;
nat brush_size $19; nat brush_size $19;
load_immediate 5 -> brush_size; load_immediate 5 -> brush_size;
call draw_box screen_buffer width selected_color mouse_x mouse_y brush_size brush_size -> void; call draw_box (screen_buffer width selected_color mouse_x mouse_y brush_size brush_size);
jump draw_loop; jump draw_loop;
@ -98,41 +212,41 @@ function main ()
exit 0; exit 0;
function set_color_if_clicked (int click_x $0, int click_y $1, function set_color_if_clicked (int click_x $0, int click_y $1,
int box_x $2, int box_y $3, byte color $4, int box_size $5) int box_x $2, int box_y $3, byte check_color $4, int bsize $5)
// Compute right // Compute right
int right_edge $6; int right_edge $6;
add_int box_x box_size -> right_edge; add_int box_x bsize -> right_edge;
// Compute bottom = box_y + box_size // Compute bottom = box_y + bsize
int bottom_edge $7; int bottom_edge $7;
add_int box_y box_size -> bottom_edge; add_int box_y bsize -> bottom_edge;
// Bounds check: x in [box_x, right] and y in [box_y, bottom] // Bounds check: x in [box_x, right] and y in [box_y, bottom]
jump_lt_int fail click_x box_x; jump_lt_int fail click_x box_x;
jump_ge_int fail click_x right_edge; jump_gt_int fail click_x right_edge;
jump_lt_int fail click_y box_y; jump_lt_int fail click_y box_y;
jump_ge_int fail click_y bottom_edge; jump_gt_int fail click_y bottom_edge;
store_absolute_8 color -> SELECTED_COLOR; store_absolute_8 check_color -> SELECTED_COLOR;
else fail else fail
return; return;
function draw_outlined_swatch(nat base $0, function draw_outlined_swatch(nat dos_base $0,
byte color $1, int x $2, int y $3, int width $4) byte swatch_color $1, int x $2, int y $3, int dos_width $4)
// Constants // Constants
nat background_color $5; nat background_color $5;
load_absolute_32 GRAY -> background_color; load_absolute_8 GRAY -> background_color;
byte selected_color $10; byte dos_selected_color $10;
load_absolute_32 SELECTED_COLOR -> selected_color; load_absolute_8 SELECTED_COLOR -> dos_selected_color;
jump_eq_int set_selected selected_color color; jump_eq_int set_selected swatch_color dos_selected_color;
jump end_set_selected; jump end_set_selected;
do set_selected do set_selected
load_absolute_32 DARK_GRAY -> background_color; load_absolute_8 DARK_GRAY -> background_color;
else end_set_selected else end_set_selected
nat outline_size $6; nat outline_size $6;
@ -141,27 +255,27 @@ function draw_outlined_swatch(nat base $0,
nat fill_size $7; nat fill_size $7;
load_immediate 17 -> fill_size; load_immediate 17 -> fill_size;
nat offset $8; nat dos_offset $8;
load_immediate 2 -> offset; load_immediate 2 -> dos_offset;
call draw_box base width background_color x y outline_size outline_size -> void; call draw_box (dos_base dos_width background_color x y outline_size outline_size);
add_int x offset -> $9; // x + 2 add_int x dos_offset -> $9; // x + 2
add_int y offset -> $10; // y + 2 add_int y dos_offset -> $10; // y + 2
call draw_box base width color $9 $10 fill_size fill_size -> void; call draw_box (dos_base dos_width swatch_color $9 $10 fill_size fill_size);
return; return;
function draw_box (nat base $0, nat screen_width $1, function draw_box (nat db_base $0, nat screen_width $1,
byte color $2, nat x_start $3, nat y_start $4, byte box_color $2, nat x_start $3, nat y_start $4,
nat width $5, nat height $6) nat db_width $5, nat height $6)
// Compute start address: base + y*640 + x // Compute start address: base + y*640 + x
nat offset $15; nat offset $15;
mul_int y_start screen_width -> offset; mul_int y_start screen_width -> offset;
add_int offset x_start -> offset; add_int offset x_start -> offset;
add_nat offset base -> offset; add_nat offset db_base -> offset;
nat fat_ptr_size $25; nat fat_ptr_size $25;
load_immediate 4 -> fat_ptr_size; load_immediate 4 -> fat_ptr_size;
add_nat offset fat_ptr_size -> offset; // need to add offset for fat pointer size add_nat offset fat_ptr_size -> offset; // need to add offset for fat pointer size
@ -172,13 +286,8 @@ function draw_box (nat base $0, nat screen_width $1,
int zero $26; int zero $26;
load_immediate 0 -> zero; load_immediate 0 -> zero;
int row_end $27;
nat pixel_ptr $29;
loop draw_box_outer loop draw_box_outer
add_int offset width -> row_end; // current + width memset_8 box_color db_width -> offset; // draw row
register_move offset -> pixel_ptr; // set pixel point
memset_8 pixel_ptr color width; // draw row
add_int offset screen_width -> offset; // next row += 640 add_int offset screen_width -> offset; // next row += 640
sub_int height i -> height; // decrement row count sub_int height i -> height; // decrement row count
jump_gt_int draw_box_outer height zero; jump_gt_int draw_box_outer height zero;

View File

@ -1,22 +0,0 @@
((code
(label main
(load-absolute-32 $0 &x)
(load-absolute-32 $1 &y)
(add-real $2 $1 $0)
(real-to-string $3 $2)
(call &pln ($3) nil)
(exit 0))
(label pln
(load-immediate $1 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(load-immediate $3 &new-line)
(string-length $2 $0)
(syscall WRITE $1 $0 $2)
(string-length $4 $3)
(syscall WRITE $1 $3 $4)
(return nil)))
(data (label terminal-namespace "/dev/term/0")
(label new-line "\n")
(label x 1.0)
(label y 2.0)))

BIN
test/simple.rom Normal file

Binary file not shown.

View File

@ -3,10 +3,10 @@ global str new_line = "\n";
function main () function main ()
load_immediate 1.0 -> $0; load_immediate 1.0 -> $0;
load_immediate 1.0 -> $1; load_immediate 2.0 -> $1;
add_real $0 $1 -> $0; add_real $0 $1 -> $0;
real_to_string $0 -> $0; real_to_string $0 -> $0;
call pln $0; call pln ($0);
exit 0; exit 0;
function pln (str message $0) function pln (str message $0)
@ -19,7 +19,7 @@ function pln (str message $0)
load_immediate 0 -> mode; load_immediate 0 -> mode;
load_address terminal_namespace -> term_ns; load_address terminal_namespace -> term_ns;
syscall OPEN term_ns mode -> term; syscall OPEN term_ns mode term;
string_length message -> msg_length; string_length message -> msg_length;
syscall WRITE term message msg_length; syscall WRITE term message msg_length;
load_address new_line -> nl; load_address new_line -> nl;

View File

@ -1,71 +0,0 @@
((code
(label main
; Open screen
; use load immediate because it is a pointer to a string, not a value
(load-immediate $18 &screen-namespace)
(syscall OPEN $0 $18 $11) ; open(out Plex screen, in namespace, in flags)
(nat-to-string $5 $0)
(call &pln ($5) nil)
(load-offset-32 $20 $0 8) ; load width
(nat-to-string $5 $20)
(call &pln ($5) nil)
(load-offset-32 $22 $0 12) ; load size
(nat-to-string $5 $22)
(call &pln ($5) nil)
(load-immediate $1 16) ; offset for screen buffer
(add-nat $21 $0 $1)
(nat-to-string $5 $21)
(call &pln ($5) nil)
; open mouse
(load-immediate $16 &mouse-namespace)
(syscall OPEN $15 $16 $11) ; open(out Plex mouse, in namespace, in flags)
(syscall WRITE $0 $21 $22) ; redraw
(label draw-loop
; load mouse click data
(syscall REFRESH $15)
(load-offset-8 $9 $15 16) ; load btn1 pressed
(jump-eq-nat &draw-loop $9 $11)
(load-offset-32 $7 $15 8) ; load x
(load-offset-32 $8 $15 12) ; load y
; Compute start address: y*width + x
(mul-nat $30 $8 $20) ; $15 = y * width
(add-nat $30 $30 $7) ; $15 += x
(add-nat $30 $30 $21) ; $15 += pixel_offset
(load-immediate $1 4) ; need to add offset for fat pointer size
(add-nat $30 $30 $1)
(load-absolute-32 $3 &WHITE) ; color
(store-absolute-8 $30 $3) ; draw color at screen [x,y]
(syscall WRITE $0 $21 $22) ; redraw
(jump &draw-loop))
(exit 0))
(label pln
(load-immediate $1 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(load-immediate $3 &new-line)
(string-length $2 $0)
(syscall WRITE $1 $0 $2)
(string-length $4 $3)
(syscall WRITE $1 $3 $4)
(return nil)))
(data
(label screen-namespace "/dev/screen/0")
(label mouse-namespace "/dev/mouse/0")
(label terminal-namespace "/dev/term/0")
(label new-line "\n")
(label WHITE 255)))

BIN
test/window.rom Normal file

Binary file not shown.

View File

@ -2,7 +2,7 @@ global str screen_namespace = "/dev/screen/0";
global str mouse_namespace = "/dev/mouse/0"; global str mouse_namespace = "/dev/mouse/0";
global str terminal_namespace = "/dev/term/0"; global str terminal_namespace = "/dev/term/0";
global str new_line = "\n"; global str new_line = "\n";
global byte white = 255; global byte WHITE = 255;
function main () function main ()
plex screen $0; plex screen $0;
@ -18,37 +18,38 @@ function main ()
nat screen_buffer $10; nat screen_buffer $10;
nat buffer_size $11; nat buffer_size $11;
nat pixel_pos $12; nat pixel_pos $12;
nat fat_ptr_size $13;
load_immediate screen_namespace -> screen; load_address screen_namespace -> screen;
load_immediate 0 -> mode; load_immediate 0 -> mode;
syscall OPEN screen mode -> screen; syscall OPEN screen mode screen;
nat_to_string screen -> tmp_str; nat_to_string screen -> tmp_str;
call pln tmp_str -> void; call pln (tmp_str);
load_offset_32 screen 8 -> width; load_offset_32 screen 8 -> width;
nat_to_string width -> tmp_str; nat_to_string width -> tmp_str;
call pln tmp_str -> void; call pln (tmp_str);
load_offset_32 screen 12 -> buffer_size; load_offset_32 screen 12 -> buffer_size;
nat_to_string buffer_size -> tmp_str; nat_to_string buffer_size -> tmp_str;
call pln tmp_str -> void; call pln (tmp_str);
load_immediate 16 -> offset_temp; load_immediate 16 -> offset_temp;
add_nat screen offset_temp -> screen_buffer; add_nat screen offset_temp -> screen_buffer;
nat_to_string screen_buffer -> tmp_str; nat_to_string screen_buffer -> tmp_str;
call pln tmp_str -> void; call pln (tmp_str);
// open mouse // open mouse
load_immediate mouse_namespace -> mouse; load_address mouse_namespace -> mouse;
syscall OPEN mouse mode -> mouse; syscall OPEN mouse mode mouse;
syscall WRITE screen screen_buffer buffer_size; // redraw syscall WRITE screen screen_buffer buffer_size; // redraw
loop draw_loop loop draw_loop
// load mouse click data // load mouse click data
syscall STAT mouse; syscall REFRESH mouse;
load_offset_8 mouse 16 -> left_down; load_offset_8 mouse 16 -> left_down;
@ -64,11 +65,12 @@ function main ()
load_immediate 4 -> fat_ptr_size; load_immediate 4 -> fat_ptr_size;
add_nat pixel_pos fat_ptr_size -> pixel_pos; add_nat pixel_pos fat_ptr_size -> pixel_pos;
load_absolute_32 white -> color; load_absolute_32 WHITE -> color;
store_absolute_8 pixel_pos color; // draw color at screen [x,y] store_absolute_8 color -> pixel_pos; // draw color at screen [x,y]
syscall WRITE screen screen_buffer buffer_size; // redraw syscall WRITE screen screen_buffer buffer_size; // redraw
jump draw_loop; jump draw_loop;
exit 0; exit 0;
function pln (str message $0) function pln (str message $0)
@ -76,12 +78,12 @@ function pln (str message $0)
int msg_length $2; int msg_length $2;
str nl $3; str nl $3;
int nl_length $4; int nl_length $4;
int mode $5; int pln_mode $5;
str term_ns $6; str term_ns $6;
load_immediate 0 -> mode; load_immediate 0 -> pln_mode;
load_address terminal_namespace -> term_ns; load_address terminal_namespace -> term_ns;
syscall OPEN term_ns mode -> term; syscall OPEN term_ns pln_mode term;
string_length message -> msg_length; string_length message -> msg_length;
syscall WRITE term message msg_length; syscall WRITE term message msg_length;
load_address new_line -> nl; load_address new_line -> nl;