Fix tests, make auto compile for rom files

This commit is contained in:
zongor 2025-10-18 16:54:06 -07:00
parent 89ef394888
commit 6c1bf1ff8c
23 changed files with 275 additions and 111 deletions

View File

@ -152,22 +152,34 @@ clean-all:
@rm -rf build/
@echo "All cleaned."
# --- HELP ---
# --- TEST COMPILATION TARGET ---
# Compiles all .asm.lisp test files to .rom using the debug VM executable
# Usage: make compile-tests PLATFORM=linux
compile-tests: $(BUILD_DIR)/undar-$(PLATFORM)$(TARGET_SUFFIX)
@echo "Compiling test assembly files for $(PLATFORM)..."
@for f in ./test/*.asm.lisp; do \
base=$$(basename "$$f" .asm.lisp); \
echo " [$$base] $$f -> ./test/$$base.rom"; \
$(BUILD_DIR)/undar-$(PLATFORM)$(TARGET_SUFFIX) "$$f" -o "./test/$$base.rom"; \
done
@echo "Compilation complete: $$(ls -1 ./test/*.rom | wc -l) ROM files generated"
# Update help target to include new command
help:
@echo "Undar VM"
@echo ""
@echo "Targets:"
@echo " make -> debug build (default: linux)"
@echo " make debug -> same as above"
@echo " make release -> optimized, stripped build"
@echo " make release -> optimized, stripped build"
@echo " make compile-tests -> compile all test assembly files"
@echo " make clean -> clean current platform"
@echo " make clean-all→ clean all platforms"
@echo " make clean-all-> clean all platforms"
@echo ""
@echo "Platforms:"
@echo " make PLATFORM=linux -> GCC + SDL2"
@echo " make PLATFORM=emscripten -> Emscripten + SDL2 for Web"
@echo " make PLATFORM=avr -> (example) AVR-GCC"
@echo ""
@echo "Output:"
@echo " Linux: build/linux/undar-linux-<debug|release>"
@echo " Web: build/emscripten/undar.html (+ .js, .wasm)"
@echo " Web: build/emscripten/undar.html (+ .js, .wasm)"

View File

@ -234,6 +234,144 @@ void repl(VM *vm) {
exit(0);
}
#ifdef ASM_DEBUG
const char *opcode_to_string(Opcode op) {
static const char *names[] = {
[OP_HALT] = "halt",
[OP_JMP] = "jump",
[OP_JMPF] = "jump-if-flag",
[OP_CALL] = "call",
[OP_RETURN] = "return",
/* Immediate loads (only 32-bit variant needed) */
[OP_LOAD_IMM] = "load-immediate",
/* Register-indirect loads */
[OP_LOAD_IND_8] = "load-indirect-8",
[OP_LOAD_IND_16] = "load-indirect-16",
[OP_LOAD_IND_32] = "load-indirect-32",
/* Absolute address loads */
[OP_LOAD_ABS_8] = "load-absolute-8",
[OP_LOAD_ABS_16] = "load-absolute-16",
[OP_LOAD_ABS_32] = "load-absolute-32",
/* Base+offset loads */
[OP_LOAD_OFF_8] = "load-offset-8",
[OP_LOAD_OFF_16] = "load-offset-16",
[OP_LOAD_OFF_32] = "load-offset-32",
/* Absolute address stores */
[OP_STORE_ABS_8] = "store-absolute-8",
[OP_STORE_ABS_16] = "store-absolute-16",
[OP_STORE_ABS_32] = "store-absolute-32",
/* Register-indirect stores */
[OP_STORE_IND_8] = "store-indirect-8",
[OP_STORE_IND_16] = "store-indirect-16",
[OP_STORE_IND_32] = "store-indirect-32",
/* Base+offset stores */
[OP_STORE_OFF_8] = "store-offset-8",
[OP_STORE_OFF_16] = "store-offset-16",
[OP_STORE_OFF_32] = "store-offset-32",
/* Memory operations */
[OP_MALLOC] = "malloc",
[OP_MEMSET_8] = "memset-8",
[OP_MEMSET_16] = "memset-16",
[OP_MEMSET_32] = "memset-32",
/* Stack operations */
[OP_PUSH] = "push",
[OP_POP] = "pop",
/* Register operations */
[OP_REG_MOV] = "register-move",
[OP_SYSCALL] = "syscall",
/* Bit operations */
[OP_SLL] = "bit-shift-left",
[OP_SRL] = "bit-shift-right",
[OP_SRE] = "bit-shift-re",
[OP_BAND] = "bit-and",
[OP_BOR] = "bit-or",
[OP_BXOR] = "bit-xor",
/* Integer arithmetic */
[OP_ADD_INT] = "add-int",
[OP_SUB_INT] = "sub-int",
[OP_MUL_INT] = "mul-int",
[OP_DIV_INT] = "div-int",
/* Natural number arithmetic */
[OP_ADD_NAT] = "add-nat",
[OP_SUB_NAT] = "sub-nat",
[OP_MUL_NAT] = "mul-nat",
[OP_DIV_NAT] = "div-nat",
/* Floating point operations */
[OP_ADD_REAL] = "add-real",
[OP_SUB_REAL] = "sub-real",
[OP_MUL_REAL] = "mul-real",
[OP_DIV_REAL] = "div-real",
/* Type conversions */
[OP_INT_TO_REAL] = "int-to-real",
[OP_NAT_TO_REAL] = "nat-to-real",
[OP_REAL_TO_INT] = "real-to-int",
[OP_REAL_TO_NAT] = "real-to-nat",
/* Integer comparisons */
[OP_JEQ_INT] = "jump-eq-int",
[OP_JNEQ_INT] = "jump-neq-int",
[OP_JGT_INT] = "jump-gt-int",
[OP_JLT_INT] = "jump-lt-int",
[OP_JLE_INT] = "jump-le-int",
[OP_JGE_INT] = "jump-ge-int",
/* Natural number comparisons */
[OP_JEQ_NAT] = "jump-eq-nat",
[OP_JNEQ_NAT] = "jump-neq-nat",
[OP_JGT_NAT] = "jump-gt-nat",
[OP_JLT_NAT] = "jump-lt-nat",
[OP_JLE_NAT] = "jump-le-nat",
[OP_JGE_NAT] = "jump-ge-nat",
/* Floating point comparisons */
[OP_JEQ_REAL] = "jump-eq-real",
[OP_JNEQ_REAL] = "jump-neq-real",
[OP_JGE_REAL] = "jump-ge-real",
[OP_JGT_REAL] = "jump-gt-real",
[OP_JLT_REAL] = "jump-lt-real",
[OP_JLE_REAL] = "jump-le-real",
/* String operations */
[OP_STRLEN] = "string-length",
[OP_STREQ] = "string-eq",
[OP_STRCAT] = "string-concat",
[OP_STR_GET_CHAR] = "string-get-char",
[OP_STR_FIND_CHAR] = "string-find-char",
[OP_STR_SLICE] = "string-slice",
/* String conversions */
[OP_INT_TO_STRING] = "int-to-string",
[OP_NAT_TO_STRING] = "nat-to-string",
[OP_REAL_TO_STRING] = "real-to-string",
[OP_STRING_TO_INT] = "string-to-int",
[OP_STRING_TO_NAT] = "string-to-nat",
[OP_STRING_TO_REAL] = "string-to-real"
};
if (op < 0 || op >= (int)(sizeof(names) / sizeof(names[0]))) {
return "<invalid-opcode>";
}
const char *name = names[op];
return name ? name : "<unknown-opcode>";
}
#endif
i32 main(i32 argc, char *argv[]) {
bool gui_mode = false;
bool dump_rom = false;
@ -397,8 +535,12 @@ i32 main(i32 argc, char *argv[]) {
int cycles_this_frame = 0;
int max_cycles_per_frame = 1000; // Adjust this value
while (cycles_this_frame < max_cycles_per_frame) {
#ifdef ASM_DEBUG
printf("| %s %d\n", opcode_to_string(vm.code[vm.pc]),vm.pc);
#endif
if (!step_vm(&vm)) {
running = false;
break;
}
cycles_this_frame++;
}

View File

@ -1,5 +1,5 @@
#include "assembler.h"
typedef enum { SYMBOL_CODE, SYMBOL_DATA, SYMBOL_PLEX } SymbolType;
typedef enum { SYMBOL_CODE, SYMBOL_DATA } SymbolType;
typedef struct {
char *name;
@ -26,10 +26,6 @@ void symbol_table_add(SymbolTable *table, const char *name, u32 address,
// Check for duplicates
for (int i = 0; i < table->count; i++) {
if (strcmp(table->symbols[i].name, name) == 0) {
// Allow plex redefinition for compiler evolution
if (type == SYMBOL_PLEX && table->symbols[i].type == SYMBOL_PLEX) {
return;
}
fprintf(stderr, "Error: Duplicate label '%s'\n", name);
exit(1);
}

View File

@ -11,9 +11,9 @@
#include <ctype.h>
#define AS_FIXED(v) ((float)(i32)(v) / 65536.0f)
#define TO_FIXED(f) ((u32)((i32)( \
#define TO_FIXED(f) ((i32)( \
((f) >= 0.0f) ? ((f) * 65536.0f + 0.5f) : ((f) * 65536.0f - 0.5f) \
)))
))
void assemble(VM *vm, ExprNode *program);

View File

@ -1,2 +0,0 @@
gcc math_gen.c -o math_gen -lm
./math_gen > ./math.h

View File

@ -1,31 +0,0 @@
#include <math.h>
#include <stdint.h>
#include <stdio.h>
int main() {
printf("#ifndef ZRE_TRIG_TABLES_H\n#define ZRE_TRIG_TABLES_H\n#include <stdint.h>\n\n");
// Generate SINE table (256 entries, Q16.16 format)
printf("const int32_t sin_table[256] = {\n");
for (int i = 0; i < 256; i++) {
double angle = i * 2 * M_PI / 256.0; // 0-360° in radians
double value = sin(angle) * 65536.0; // Scale to Q16.16
int32_t fixed = (int32_t)(value + 0.5); // Round to nearest
printf(" %d,", fixed);
if (i % 8 == 7) printf("\n");
}
printf("};\n\n");
// Generate COSINE table (256 entries, Q16.16 format)
printf("const int32_t cos_table[256] = {\n");
for (int i = 0; i < 256; i++) {
double angle = i * 2 * M_PI / 256.0; // 0-360° in radians
double value = cos(angle) * 65536.0; // Scale to Q16.16
int32_t fixed = (int32_t)(value + 0.5); // Round to nearest
printf(" %d,", fixed);
if (i % 8 == 7) printf("\n");
}
printf("};\n");
printf("#endif\n");
return 0;
}

View File

@ -108,8 +108,9 @@ void fixed_to_string(i32 value, char *buffer) {
char temp[32];
i32 negative;
u32 int_part;
u32 frac_part, frac_digits;
u32 frac_part, frac_digits, original_frac_digits;
char *end = temp + sizeof(temp) - 1;
char *frac_start;
*end = '\0';
negative = 0;
@ -122,14 +123,40 @@ void fixed_to_string(i32 value, char *buffer) {
frac_part = AS_NAT(value & 0xFFFF);
/* Convert fractional part to 5 decimal digits */
frac_digits = (frac_part * 100000U) / 65536U;
original_frac_digits = (frac_part * 100000U) / 65536U;
frac_digits = original_frac_digits;
if (frac_digits > 0) {
end = write_digits_backwards(frac_digits, end, temp);
/* Write fractional digits backwards */
frac_start = write_digits_backwards(frac_digits, end, temp);
/* Remove trailing zeros by moving the start pointer */
while (*(end - 1) == '0' && end > frac_start) {
end--;
}
/* If all fractional digits were zeros after removing trailing zeros,
we need to add back one zero to represent the .0 */
if (end == frac_start) {
*--end = '0';
}
/* Add decimal point */
*--end = '.';
} else if (frac_part > 0) {
/* Handle case where original_frac_digits was rounded to 0 but frac_part was not 0 */
/* This means we have a very small fractional part that should be represented as .0 */
*--end = '0';
*--end = '.';
} else if (frac_part == 0) {
/* No fractional part - just add .0 if we have an integer part */
if (int_part != 0) {
*--end = '0';
*--end = '.';
}
}
if (int_part == 0 && frac_digits == 0) {
if (int_part == 0 && frac_digits == 0 && frac_part == 0) {
*--end = '0';
} else {
end = write_digits_backwards(int_part, end, temp);
@ -140,4 +167,4 @@ void fixed_to_string(i32 value, char *buffer) {
}
strcopy(buffer, end, temp + sizeof(temp) - end);
}
}

View File

@ -8,7 +8,7 @@
(pop $0)
(int-to-string $1 $0)
(push $1)
(call &println)
(call &pln)
(halt))
(label add
@ -18,15 +18,17 @@
(push $2)
(return))
(label println
(load-immediate $0 &terminal-namespace)
(syscall OPEN $0 $0 $0)
(label pln
(load-immediate $0 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $0 $0 $11)
(load-immediate $3 &new-line)
(pop $1)
(load-offset-32 $7 $0 4) ; load handle
(string-length $2 $1)
(syscall WRITE $0 $1 $2)
(syscall WRITE $7 $1 $2)
(string-length $4 $3)
(syscall WRITE $0 $3 $4)
(syscall WRITE $7 $3 $4)
(return)))
(data
(label terminal-namespace "/dev/term/0")

Binary file not shown.

View File

@ -28,15 +28,17 @@
(label base-case
(push $0)
(return)))
(label pln
(load-immediate $0 &terminal-namespace)
(syscall OPEN $0 $0 $0)
(label pln
(load-immediate $0 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $0 $0 $11)
(load-immediate $3 &new-line)
(pop $1)
(load-offset-32 $7 $0 4) ; load handle
(string-length $2 $1)
(syscall WRITE $0 $1 $2)
(syscall WRITE $7 $1 $2)
(string-length $4 $3)
(syscall WRITE $0 $3 $4)
(syscall WRITE $7 $3 $4)
(return)))
(data
(label terminal-namespace "/dev/term/0")

Binary file not shown.

View File

@ -1,11 +1,22 @@
((code
(label main
(load-immediate $0 &terminal-namespace) ; load terminal namespace
(syscall OPEN $0 $0 $0)
(load-immediate $1 &hello-str) ; load hello string ptr
(string-length $2 $1) ; get length to write to stdout
(syscall WRITE $0 $1 $2) ; do the write syscall
(halt))) ; done
(push $1)
(call &pln)
(halt)) ; done
(label pln
(load-immediate $0 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $0 $0 $11)
(load-immediate $3 &new-line)
(pop $1)
(load-offset-32 $7 $0 4) ; load handle
(string-length $2 $1)
(syscall WRITE $7 $1 $2)
(string-length $4 $3)
(syscall WRITE $7 $3 $4)
(return)))
(data
(label terminal-namespace "/dev/term/0")
(label hello-str "nuqneH 'u'?\n")))
(label new-line "\n")
(label hello-str "nuqneH 'u'?")))

Binary file not shown.

View File

@ -27,16 +27,18 @@
(push $3)
(call &pln)
(halt))
(label pln
(load-immediate $0 &terminal-namespace)
(syscall OPEN $0 $0 $0)
(load-immediate $3 &new-line)
(pop $1)
(string-length $2 $1)
(syscall WRITE $0 $1 $2)
(string-length $4 $3)
(syscall WRITE $0 $3 $4)
(return)))
(label pln
(load-immediate $0 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $0 $0 $11)
(load-immediate $3 &new-line)
(pop $1)
(load-offset-32 $7 $0 4) ; load handle
(string-length $2 $1)
(syscall WRITE $7 $1 $2)
(string-length $4 $3)
(syscall WRITE $7 $3 $4)
(return)))
(data
(label terminal-namespace "/dev/term/0")
(label help "Enter a string: ")

Binary file not shown.

View File

@ -1,25 +1,33 @@
((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
(push $0)
(push $1)
(call &pln)
(load-immediate $1 32) ; read in a string of max 32 char length
(malloc $2 $1) ; allocate memory for the string
(syscall READ $0 $3 $1 $2) ; read the string
(push $3)
(malloc $4 $1) ; allocate memory for the string
(load-offset-32 $7 $0 4) ; load handle
(syscall READ $7 $2 $1 $4) ; read the string
(push $0)
(push $4)
(call &pln) ; print the string
(halt))
(label pln
(load-immediate $0 &terminal-namespace)
(syscall OPEN $0 $0 $0)
(load-immediate $3 &new-line)
(pop $1)
(string-length $2 $1)
(syscall WRITE $0 $1 $2)
(string-length $4 $3)
(syscall WRITE $0 $3 $4)
(return)))
(label pln
(load-immediate $3 &new-line)
(pop $1)
(pop $0)
(load-offset-32 $7 $0 4) ; load handle
(string-length $2 $1)
(syscall WRITE $7 $1 $2)
(string-length $4 $3)
(syscall WRITE $7 $3 $4)
(return)))
(data
(label terminal-namespace "/dev/term/0")
(label help "Enter a string: ")

BIN
test/malloc.rom Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

Binary file not shown.

View File

@ -43,14 +43,7 @@
(load-immediate $16 &mouse-namespace)
(syscall OPEN $15 $16 $11) ; open(out Plex mouse, in namespace, in flags)
(load-immediate $1 4) ; offset for handle
(add-nat $19 $15 $1)
(nat-to-string $5 $19)
(push $32)
(push $5)
(call &pln)
(load-indirect-32 $16 $19) ; load handle
(load-offset-32 $16 $15 4) ; load handle
(syscall WRITE $0 $21 $22) ; redraw

Binary file not shown.