all repos — xyw @ a7dabec991e09820cd375734d8ae6c03cb4cda3a

A minimal virtual machine and assembler for terminals.

Fixes.
h3rald h3rald@h3rald.com
Mon, 01 Dec 2025 16:04:53 +0100
commit

a7dabec991e09820cd375734d8ae6c03cb4cda3a

parent

d730c86485a9e5029bdb0e8fbce2bd9dd052db03

3 files changed, 28 insertions(+), 27 deletions(-)

jump to
M xyw.hxyw.h

@@ -4,17 +4,18 @@

#define XYW_MODE_X 0x20 #define XYW_MODE_Y 0x40 #define XYW_MODE_W 0x80 +#define XYW_TOTAL_INSTRUCTIONS 0x20 + // clang-format off -#define dbg(...) do { if (xyw_debug) fprintf(stdout, __VA_ARGS__); } while(0) +#define xyw_dbg(...) do { if (xyw_debug) fprintf(stdout, __VA_ARGS__); } while(0) // clang-format on typedef unsigned char xyw_byte; typedef unsigned short xyw_word; extern const char xyw_instructions[][4]; -// Number of instruction mnemonics -#define XYW_INSTRUCTION_COUNT 32 extern int xyw_debug; + int xyw_assemble(const char *input, const char *output); int run(const char *input);
M xywasm.cxywasm.c

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

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

@@ -349,7 +349,7 @@ token_error("Invalid hex digit");

return -1; } } - dbg("Hex number:\t%s\t(%04X)\n", token, value); + xyw_dbg("Hex number:\t%s\t(%04X)\n", token, value); } else if (token[0] == '%') {

@@ -367,7 +367,7 @@ token_error("Invalid binary digit");

return -1; } } - dbg("Binary number:\t%s\t(%04X)\n", token, value); + xyw_dbg("Binary number:\t%s\t(%04X)\n", token, value); } else {

@@ -393,7 +393,7 @@ if (negative)

{ value = -value; } - dbg("Decimal number:\t%s\t(%04X)\n", token, value); + xyw_dbg("Decimal number:\t%s\t(%04X)\n", token, value); } token_type = TOKEN_TYPE_NUMBER; token_value = value;

@@ -409,7 +409,7 @@ {

(void)ctx; xyw_byte opcode = 0; // Match token against instruction mnemonics - for (unsigned int i = 0; i < XYW_INSTRUCTION_COUNT; i++) + for (unsigned int i = 0; i < XYW_TOTAL_INSTRUCTIONS; i++) { if (strcmpn(token, xyw_instructions[i], 3) == 0) {

@@ -444,7 +444,7 @@ }

} char bits[9]; byte_to_binary(opcode, bits); - dbg("Instruction:\t%s\t(%02X - %s)\n", token, opcode, bits); + xyw_dbg("Instruction:\t%s\t(%02X - %s)\n", token, opcode, bits); token_type = TOKEN_TYPE_INSTRUCTION; token_value = opcode; append(opcode);

@@ -457,7 +457,7 @@

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

@@ -477,7 +477,7 @@ {

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

@@ -498,7 +498,7 @@ }

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

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

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

@@ -534,7 +534,7 @@ {

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

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

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

@@ -560,7 +560,7 @@ {

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

@@ -573,7 +573,7 @@

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

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

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

@@ -934,7 +934,7 @@ return -1;

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

@@ -109,7 +109,7 @@ {

xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_OVERFLOW; return; } - printf(" => %02X\n", val); + xyw_dbg(" => %02X\n", val); user_stack[(*usp)++] = val; }

@@ -121,7 +121,7 @@ xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_OVERFLOW;

return; } mset(USER_STACK_START + *usp, val); - printf(" => %04X\n", val); + xyw_dbg(" => %04X\n", val); (*usp) += 2; }

@@ -461,7 +461,7 @@ return -1;

} // Check header xyw_byte header[6]; - dbg("Reading header from file [%s]\n", input); + xyw_dbg("Reading header from file [%s]\n", input); fread(header, 1, 6, fp); if (header[0] != 0x0F || header[1] != 'x' || header[2] != 'y' || header[3] != 'w' || header[4] != 0x00 || header[5] != 0xF0) {

@@ -469,7 +469,7 @@ fprintf(stderr, "Error - Invalid file header [%s]\n", input);

fclose(fp); return -1; } - dbg("File header OK\n"); + xyw_dbg("File header OK\n"); // Load the rest of the file into memory size_t bytes_read = fread(&xyw_memory[USER_MEMORY_START], 1, MEMORY_SIZE - USER_MEMORY_START, fp); if (bytes_read == 0)

@@ -478,12 +478,12 @@ fprintf(stderr, "Error - Could not read file contents [%s]\n", input);

fclose(fp); return -1; } - dbg("Loaded %zu bytes into memory\n", bytes_read); + xyw_dbg("Loaded %zu bytes into memory\n", bytes_read); fclose(fp); xyw_memory[SYSTEM_STATE] = 1; - while (xyw_memory[SYSTEM_STATE] && *pc < 20) + while (xyw_memory[SYSTEM_STATE] && *pc < SYSTEM_MEMORY_START) { - dbg("PC: %04X -> %02X (%s)\n", *pc, xyw_memory[*pc], xyw_instructions[xyw_memory[*pc] & 0x1F]); + xyw_dbg("PC: %04X -> %02X (%s)\n", *pc, xyw_memory[*pc], xyw_instructions[xyw_memory[*pc] & 0x1F]); switch (xyw_memory[*pc]) { // clang-format off