all repos — xyw @ 34611e9a0ba909021525fbc68fe94c37029298de

A minimal virtual machine and assembler for terminals.

Standardized debugging.
h3rald h3rald@h3rald.com
Fri, 28 Nov 2025 15:36:14 +0100
commit

34611e9a0ba909021525fbc68fe94c37029298de

parent

ee6b5ab02beb5d628b9111fd8aba5365d54841fc

4 files changed, 36 insertions(+), 25 deletions(-)

jump to
M MakefileMakefile

@@ -12,7 +12,7 @@

xyw.o: xyw.c xyw.h $(CC) $(CFLAGS) -c xyw.c -o xyw.o -xywasm.o: xywasm.c +xywasm.o: xywasm.c xyw.h $(CC) $(CFLAGS) -c xywasm.c -o xywasm.o clean:
M xyw.cxyw.c

@@ -64,6 +64,8 @@ #define BUZZER_SAMPLES 0x51

#define BUZZER_N_SAMPLES 0x53 #define BUZZER_ON_STOP 0x55 +int xyw_debug = 0; + xyw_byte xyw_memory[MEMORY_SIZE]; xyw_byte system_stack[STACK_SIZE]; xyw_byte user_stack[STACK_SIZE];

@@ -109,7 +111,13 @@ //// Main Function

int main(int argc, char *argv[]) { (void)argc; - (void)argv; + for (int i = 1; i < argc; i++) + { + if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) + { + xyw_debug = 1; + } + } // If first argument is a file ending in .xyw, assemble it if (argc >= 2) {
M xyw.hxyw.h

@@ -4,6 +4,7 @@

typedef unsigned char xyw_byte; typedef unsigned short xyw_word; +extern int xyw_debug; int xyw_assemble(const char *input, const char *output); #endif // XYW_H
M xywasm.cxywasm.c

@@ -14,6 +14,8 @@

#define error(msg) fprintf(stderr, "Error - %s [%s]\n", msg, ctx->file) #define token_error(msg) fprintf(stderr, "Error - %s: %s [%s - Ln %d, Col %d]\n", token, msg, ctx->file, ctx->line, ctx->column) #define symbol_error(symbol, msg) fprintf(stderr, "Error - %s: %s [%s - Ln %d, Col %d]\n", symbol, msg, ctx->file, ctx->line, ctx->column) +// clang-format off +#define dbg(...) do { if (xyw_debug) fprintf(stdout, __VA_ARGS__); } while(0) #define PSH 0x01

@@ -91,7 +93,7 @@

// Current write pointer xyw_word ptr = 0x0000; -// Dictionary for symbols (macros and labels) +// Flat single-string "dictionary" for symbols (macros and labels) // Actually following Uxn design here ;) char dict[0x8000]; char *dictnext = dict;

@@ -161,6 +163,7 @@ static int assemble_string(xyw_context *ctx);

static int assemble_file(xyw_context *ctx); //// Utilities + static int find_symbol(char *name) {

@@ -243,6 +246,7 @@ }

return 0; } +// Write raw bytecode data to a specified address static inline void write(xyw_word addr, xyw_word val) { if (val > 0xff)

@@ -267,6 +271,7 @@ (val > 0xff) ? append(PSH | MODE_W) : append(PSH);

append(val); } +// Store macro definition in dictionary static int macro(xyw_context *ctx, char *name, char *contents) { if (symcount >= MAX_SYMBOLS)

@@ -286,6 +291,7 @@ sym->contents = dict_store(contents);

return 0; } +// Store label in dictionary static int label(xyw_context *ctx, char *name) { if (symcount >= MAX_SYMBOLS)

@@ -305,6 +311,7 @@ sym->address = ptr;

return 0; } +// Store reference in dictionary static int ref(xyw_context *ctx, char *name) { if (refcount >= MAX_REFS)

@@ -325,7 +332,7 @@ static int process_comment(xyw_context *ctx)

{ (void)ctx; token_type = TOKEN_TYPE_COMMENT; - printf("Comment:\t%s\n", token); + dbg("Comment:\t%s\n", token); return 0; }

@@ -355,8 +362,7 @@ token_error("Invalid hex digit");

return -1; } } - // TODO: Remove - printf("Hex number:\t%s\t(%04X)\n", token, value); + dbg("Hex number:\t%s\t(%04X)\n", token, value); token_type = TOKEN_TYPE_NUMBER; token_value = value; if (!directive)

@@ -388,8 +394,7 @@ token_error("Invalid binary digit");

return -1; } } - // TODO: Remove - printf("Binary number:\t%s\t(%04X)\n", token, value); + dbg("Binary number:\t%s\t(%04X)\n", token, value); token_type = TOKEN_TYPE_NUMBER; token_value = value; if (!directive)

@@ -427,8 +432,7 @@ if (is_negative)

{ value = -value; } - // TODO: Remove - printf("Decimal number:\t%s\t(%04X)\n", token, value); + dbg("Decimal number:\t%s\t(%04X)\n", token, value); token_type = TOKEN_TYPE_NUMBER; token_value = value; if (!directive)

@@ -492,10 +496,9 @@ return -1;

} } } - // TODO: Remove char bits[9]; byte_to_binary(opcode, bits); - printf("Instruction:\t%s\t(%02X - %s)\n", token, opcode, bits); + dbg("Instruction:\t%s\t(%02X - %s)\n", token, opcode, bits); token_type = TOKEN_TYPE_INSTRUCTION; token_value = opcode; if (!directive)

@@ -515,8 +518,7 @@

static int process_string(xyw_context *ctx) { (void)ctx; - // TODO: Remove - printf("String:\t\t%s\n", token); + dbg("String:\t\t%s\n", token); token_type = TOKEN_TYPE_STRING; return 0; }

@@ -536,7 +538,7 @@ {

xyw_symbol *sym = &symbols[i]; if (sym->type == SYMBOL_TYPE_MACRO) { - printf("Macro:\t\t%s -> %s\n", token, sym->contents); + dbg("Macro:\t\t%s -> %s\n", token, sym->contents); ctx->sp = sym->contents; assemble_string(ctx); ctx->src = SRC_FILE;

@@ -557,7 +559,7 @@ }

else { // Store reference to be resolved later - printf("Reference:\t%s\n", token); + dbg("Reference:\t%s\n", token); if (ref(ctx, token) != 0) { return -1;

@@ -580,7 +582,7 @@ if (process_number(ctx) != 0)

{ return -1; } - printf("Directive:\t.org %s\n", token); + dbg("Directive:\t.org %s\n", token); // Move the pointer to the specified address ptr = (xyw_word)token_value; return validate_single_directive_argument(ctx, r);

@@ -597,7 +599,7 @@ if (process_symbol(ctx) != 0)

{ return -1; } - printf("Directive:\t.label %s\n", token); + dbg("Directive:\t.label %s\n", token); label(ctx, token); return validate_single_directive_argument(ctx, r); }

@@ -610,7 +612,7 @@ {

return -1; } process_string(ctx); - printf("Directive:\t.include %s\n", token); + dbg("Directive:\t.include %s\n", token); xyw_context include_ctx; include_ctx.src = SRC_FILE; // Ignore token quotes for file name

@@ -622,9 +624,9 @@ if (validate_single_directive_argument(ctx, r) != 0)

{ return -1; } - printf("-> Accessing:\t%s\n", include_ctx.file); + dbg("-> Accessing:\t%s\n", include_ctx.file); int result = assemble_file(&include_ctx); - printf("<- Continuing:\t%s\n", ctx->file); + dbg("<- Continuing:\t%s\n", ctx->file); return result; }

@@ -636,7 +638,7 @@ {

return -1; } process_string(ctx); - printf("Directive:\t.string %s\n", token); + dbg("Directive:\t.string %s\n", token); // Store string in memory (without quotes) for (unsigned int i = 1; i < token_length - 1; i++) {

@@ -649,7 +651,7 @@

static int process_directive_byte(xyw_context *ctx) { xyw_token_terminator r; - printf("Directive:\t.byte\n"); + dbg("Directive:\t.byte\n"); while (1) { r = next_token(ctx);

@@ -686,7 +688,7 @@ if (process_symbol(ctx) != 0)

{ return -1; } - printf("Directive:\t.macro %s\n", token); + dbg("Directive:\t.macro %s\n", token); char c; char contents[DIRECTIVE_CONTENT_MAX_LENGTH]; int length = 0;

@@ -1019,7 +1021,7 @@ return -1;

} // Patch the data at the reference address with the label address write(refsym->address, defsym->address); - printf("Patch:\t\t%s -> $%04X @ $%04X\n", defsym->name, defsym->address, refsym->address); + dbg("Patch:\t\t%s -> $%04X @ $%04X\n", defsym->name, defsym->address, refsym->address); } fwrite(data, 1, ptr, fp); fclose(fp);