all repos — xyw @ c521655f233ec78fce8b9d3fd78e7997438b3d8f

A minimal virtual machine and assembler for terminals.

Simplified image exec (removed explicit triggering)
h3rald h3rald@h3rald.com
Wed, 22 Jul 2026 14:18:59 +0200
commit

c521655f233ec78fce8b9d3fd78e7997438b3d8f

parent

4f11cb9c874e5baa2c1adf150c2949688a6edbe6

3 files changed, 42 insertions(+), 70 deletions(-)

jump to
M devices/system.cdevices/system.c

@@ -8,24 +8,17 @@ #define SYSTEM_ERROR 0x01

#define SYSTEM_PAGE 0x02 #define SYSTEM_RANDOM 0x03 #define SYSTEM_IMAGE_EXEC 0x06 -#define SYSTEM_IMAGE_EXEC_TRIGGER 0x08 - -#define SYSTEM_IMAGE_EXEC_DIRECTION 0x01 // 0 = exec child, 1 = return to parent -#define SYSTEM_IMAGE_EXEC_PRESERVE 0x02 // EXEC only: snapshot self to be able to return to previous image void system_setup(xyw_byte *data) { (void)data; - // Initialize random generator seed srand(time(NULL)); } xyw_byte system_input(xyw_byte *data, xyw_byte addr, xyw_byte *error) { if (addr == SYSTEM_RANDOM) - { return (xyw_byte)(rand() & 0xFF); - } (void)error; return data[addr]; }

@@ -33,20 +26,10 @@

void system_output(xyw_byte *data, xyw_byte addr, xyw_byte *error) { (void)error; - if (addr == SYSTEM_IMAGE_EXEC_TRIGGER && data[SYSTEM_IMAGE_EXEC_TRIGGER] != 0) + if (addr == SYSTEM_IMAGE_EXEC + 1) { - xyw_byte trig = data[SYSTEM_IMAGE_EXEC_TRIGGER]; - data[SYSTEM_IMAGE_EXEC_TRIGGER] = 0; - if (trig & SYSTEM_IMAGE_EXEC_DIRECTION) - { - xyw_request_return(); - } - else - { - xyw_word target = XYW_PEEKW(&data[SYSTEM_IMAGE_EXEC]); - if (target != 0) { - xyw_request_exec(target, trig & SYSTEM_IMAGE_EXEC_PRESERVE); - } - } + xyw_word target = XYW_PEEKW(&data[SYSTEM_IMAGE_EXEC]); + if (target != 0) + xyw_request_exec(target); } -}+}
M xyw.hxyw.h

@@ -54,6 +54,5 @@ int xyw_assemble(const char *input, const char *output);

int xyw_run(const char *input); int xyw_eval(xyw_word pc); void xyw_request_exec(xyw_word path_addr, int preserve); -void xyw_request_return(void); #endif // XYW_H
M xywrun.cxywrun.c

@@ -453,9 +453,7 @@

static xyw_image_snapshot exec_stack[MAX_IMAGE_EXEC_DEPTH]; static int exec_stack_depth = 0; static int exec_pending = 0; -static int exec_preserve = 0; static char exec_path_buf[MAX_IMAGE_EXEC_PATH_LENGTH]; -static int return_pending = 0; // Read a null-terminated string out of VM memory into a local buffer static void get_string_from_memory(xyw_word addr, char *buf, size_t bufsize)

@@ -466,16 +464,10 @@ buf[i] = xyw_memory[addr + i];

buf[i] = '\0'; } -void xyw_request_exec(xyw_word path_addr, int preserve) +void xyw_request_exec(xyw_word path_addr) { get_string_from_memory(path_addr, exec_path_buf, sizeof(exec_path_buf)); - exec_preserve = preserve; exec_pending = 1; -} - -void xyw_request_return(void) -{ - return_pending = 1; } static void split_exec_string(char *full, char **path, char **argstart)

@@ -595,44 +587,27 @@ if (xyw_devices[i].setup)

xyw_devices[i].setup(xyw_devices[i].data); } -static void handle_exec_return_requests(void) +static void handle_exec_requests(void) { - if (exec_pending) - { - exec_pending = 0; - if (exec_preserve) - { - if (exec_stack_depth >= MAX_IMAGE_EXEC_DEPTH) - { - xyw_memory[SYSTEM_ERROR] = XYW_ERROR_EXEC_DEPTH_EXCEEDED; - return; - } - save_snapshot(&exec_stack[exec_stack_depth++]); - } - // preserve == 0: one-way handoff — no push, no way back to this image + if (!exec_pending) + return; + exec_pending = 0; - char path_copy[MAX_IMAGE_EXEC_PATH_LENGTH]; - strncpy(path_copy, exec_path_buf, sizeof(path_copy) - 1); - path_copy[sizeof(path_copy) - 1] = '\0'; - char *path, *argstart; - split_exec_string(path_copy, &path, &argstart); - - reset_vm_state(); - load_and_launch(path, argstart); - } - else if (return_pending) + if (exec_stack_depth >= MAX_IMAGE_EXEC_DEPTH) { - return_pending = 0; - if (exec_stack_depth > 0) - { - restore_snapshot(&exec_stack[--exec_stack_depth]); - } - else - { - // No parent to return to — behaves like HLT - xyw_memory[SYSTEM_STATE] &= ~SYSTEM_STATE_RUNNING; - } + xyw_memory[SYSTEM_ERROR] = XYW_ERROR_EXEC_DEPTH_EXCEEDED; + return; } + save_snapshot(&exec_stack[exec_stack_depth++]); + + char path_copy[MAX_IMAGE_EXEC_PATH_LENGTH]; + strncpy(path_copy, exec_path_buf, sizeof(path_copy) - 1); + path_copy[sizeof(path_copy) - 1] = '\0'; + char *path, *argstart; + split_exec_string(path_copy, &path, &argstart); + + reset_vm_state(); + load_and_launch(path, argstart); } //// Main evaluation function - runs from current pc until BRK

@@ -650,13 +625,28 @@ if (xyw_debug)

{ xyw_memory[SYSTEM_STATE] |= SYSTEM_STATE_DEBUG; } - while ((system_running_state()) && *pc < DEVICE_AREA_START) + while (1) { + if (*pc >= DEVICE_AREA_START) + { + xyw_memory[SYSTEM_STATE] &= ~SYSTEM_STATE_RUNNING; + } + if (!system_running_state()) + { + if (exec_stack_depth > 0) + { + restore_snapshot(&exec_stack[--exec_stack_depth]); + continue; // resume the parent exactly where it left off + } + break; // no parent -- genuinely done + } + process_events(); dispatch_vectors(); - handle_exec_return_requests(); - if (!system_running_state()) { - break; // exec/return may have halted or swapped mid-iteration + handle_exec_requests(); + if (!system_running_state()) + { + continue; } XYW_DBG(" -- PC: %04X -> %02X (%s) [U:%02X|S:%02X|X:%02X|Y:%02X|XW:%04X|YW:%04X]\n", *pc, xyw_memory[*pc], xyw_instructions[xyw_memory[*pc] & 0x1F], u, s, *x, *y, *xw, *yw); switch (xyw_memory[*pc])