all repos — xyw @ 8f83ba6c8680326389ba40de23c5dbef77b5c995

A minimal virtual machine and assembler for terminals.

Implementing error handling.
h3rald h3rald@h3rald.com
Tue, 03 Feb 2026 15:33:27 +0100
commit

8f83ba6c8680326389ba40de23c5dbef77b5c995

parent

5e297f50f8612789fa337ee331e2428641536af2

2 files changed, 69 insertions(+), 5 deletions(-)

jump to
A examples/on-error.xyw

@@ -0,0 +1,31 @@

+.include "devices.xyw" + +; register on error handler +on_error system.on_error STW + +; main program +$10 $0 DIV +end JMPw + +; on error handler +.label on_error + system.error $1 EQU on_error.print JCNw + RTS + .label on_error.print + ;error print JSRw + $55 $fe00 STBw + $0 system.error STB + RTS + +; a16 -- +; printing subroutine +.label print + POPxw + .label print.loop + LDBxw terminal.output STB + INCxw LDBxw print.loop JCNw + RTS + +.label error +.string "Error: Division by zero.\n" +.label end
M xywrun.cxywrun.c

@@ -43,12 +43,17 @@ #endif

typedef enum { XYW_ERROR_NONE = 0, + XYW_ERROR_DIVISION_BY_ZERO, XYW_ERROR_INVALID_INSTRUCTION, XYW_ERROR_STACK_UNDERFLOW, XYW_ERROR_STACK_OVERFLOW, XYW_ERROR_DEVICE_UNAVAILABLE, XYW_ERROR_INVALID_DEVICE_PORT } xyw_error; + +#define SYSTEM_STATE_RUNNING 0x01 +#define SYSTEM_STATE_DEBUG 0x40 +#define SYSTEM_STATE_ERROR 0x80 /// Main memory and stacks xyw_byte xyw_memory[MEMORY_SIZE];

@@ -293,8 +298,36 @@ //// Returns 1 on success, 0 on error

int xyw_eval(xyw_word start_pc) { *pc = start_pc; - while (xyw_memory[SYSTEM_STATE] && *pc < SYSTEM_MEMORY_START) + if (xyw_memory[SYSTEM_STATE] & xyw_debug) { + xyw_memory[SYSTEM_STATE] |= SYSTEM_STATE_DEBUG; + } + + while ((xyw_memory[SYSTEM_STATE] & SYSTEM_STATE_RUNNING) && *pc < SYSTEM_MEMORY_START) + { + printf("ERROR: %d - State: %04X\n", xyw_memory[SYSTEM_ERROR], xyw_memory[SYSTEM_STATE]); + if (xyw_memory[SYSTEM_ERROR] == XYW_ERROR_NONE) + { + // Clear error state if no error + xyw_memory[SYSTEM_STATE] &= ~SYSTEM_STATE_ERROR; + } + if (xyw_memory[SYSTEM_ERROR] != XYW_ERROR_NONE && !(xyw_memory[SYSTEM_STATE] & SYSTEM_STATE_ERROR)) + { + // An error has occurred, update state + xyw_memory[SYSTEM_STATE] |= SYSTEM_STATE_ERROR; + xyw_word on_error_handler = XYW_PEEKW(&xyw_memory[SYSTEM_ON_ERROR]); + // If an error handler is set, jump to it + if (on_error_handler != 0) + { + ss_pushw(*pc); + *pc = on_error_handler; + } + else + { + // No error handler, halt execution + return xyw_memory[SYSTEM_ERROR]; + } + } 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]) {

@@ -325,7 +358,7 @@ /* SHR */ OPC_SR1r(0x0B, xyw_byte val = us_pop(); SET(ARGX >> val); SET(ARGY >> val); );

/* ADD */ OPC_SR2(0x0C, PUSH(a + b)); /* SUB */ OPC_SR2(0x0D, PUSH(a - b)); /* MUL */ OPC_SR2(0x0E, PUSH(a * b)); - /* DIV */ OPC_SR2(0x0F, PUSH(a % b); PUSH(a / b)); + /* DIV */ OPC_SR2(0x0F, printf("b: %d\n", b); if (b) { PUSH(a % b); PUSH(a / b); } else { xyw_memory[SYSTEM_ERROR] = XYW_ERROR_DIVISION_BY_ZERO; } ); /* EQU */ OPC_SR2(0x10, PUSH(a == b)); /* NEQ */ OPC_SR2(0x11, PUSH(a != b)); /* GTH */ OPC_SR2(0x12, PUSH(a > b));

@@ -341,7 +374,7 @@ /* DUP */ OPC_SR1r(0x19, SETX(READ(USER_STACK_START + (*u) - (w ? 2 : 1))); SETY(READ(USER_STACK_START + (*u) - (w ? 2 : 1))); );

/* OVR */ OPC_SR2(0x1A, PUSH(b); PUSH(a); PUSH(b)); /* ROT */ OPC_SR2(0x1B, PUSH(b); PUSH(POP()); PUSH(a)); /* JMP */ OPC_SR1(0x1C, , *pc = ADDR(ARG)-1;); - /* JCN */ OPC_SR1(0x1D, xyw_word addr = ADDR(ARG), if (us_pop()) { *pc = addr-1; }); + /* JCN */ OPC_SR1(0x1D, , xyw_word addr = ADDR(ARG); xyw_byte cond = us_pop(); printf("JCN to %04X if %d\n", addr, cond); if (cond) { *pc = addr-1; }); /* JSR */ OPC_SR1(0x1E, xyw_word addr = ADDR(ARG), ss_pushw(*pc+1); *pc = addr-1;); /* RTS */ case 0x1F: *pc = ss_popw()-1; break; // clang-format on

@@ -370,7 +403,7 @@ return -1;

} xyw_dbg("Loaded %zu bytes into memory\n", bytes_read); fclose(fp); - xyw_memory[SYSTEM_STATE] = 1; + xyw_memory[SYSTEM_STATE] |= SYSTEM_STATE_RUNNING; // Initialize devices for (int i = 0; i < XYW_TOTAL_DEVICES; i++) {

@@ -391,7 +424,7 @@ // If terminal vector is set, enter stdin reading loop

if (terminal_vector) { xyw_dbg("terminal.on_keypress vector set to %04X, entering input loop\n", terminal_vector); - while (xyw_memory[SYSTEM_STATE]) + while (xyw_memory[SYSTEM_STATE] & SYSTEM_STATE_RUNNING) { int c = getch(); // if CTRL+C or CTRL+D is pressed, exit