all repos — xyw @ b9e49abc0175c303241447ac90a14d3f07c3cd2c

A minimal virtual machine and assembler for terminals.

Started to implement runtime.
h3rald h3rald@h3rald.com
Mon, 01 Dec 2025 11:19:30 +0100
commit

b9e49abc0175c303241447ac90a14d3f07c3cd2c

parent

def4bdbcc06eb931aa7fab214efc8195b58df826

2 files changed, 118 insertions(+), 127 deletions(-)

jump to
M xywasm.cxywasm.c

@@ -84,7 +84,7 @@ // Tracks whether we are inside a directive or not

static unsigned int directive = 0; // Bytecode to be written, including header -xyw_byte data[0xffff] = { (xyw_byte)0xFA, (xyw_byte)'x', (xyw_byte)'y', (xyw_byte)'w', (xyw_byte)0x00, (xyw_byte)0xAF }; +xyw_byte data[0xffff] = { (xyw_byte)0x0F, (xyw_byte)'x', (xyw_byte)'y', (xyw_byte)'w', (xyw_byte)0x00, (xyw_byte)0xF0 }; // Current write pointer starts after header xyw_word ptr = 6;
M xywrun.cxywrun.c

@@ -21,11 +21,6 @@ #define SYSTEM_STATE 0x00

#define SYSTEM_ERROR 0x01 #define SYSTEM_SSP 0x02 #define SYSTEM_USP 0x03 -#define SYSTEM_X 0x04 -#define SYSTEM_Y 0x05 -#define SYSTEM_XW 0x06 -#define SYSTEM_YW 0x08 -#define SYSTEM_PC 0x0A #define SYSTEM_PAGE 0x0C #define SYSTEM_ON_ERROR 0x0D

@@ -76,11 +71,16 @@ xyw_byte xyw_memory[MEMORY_SIZE];

xyw_byte system_stack[STACK_SIZE]; xyw_byte user_stack[STACK_SIZE]; -//// 1-byte pointers +//// 1-byte pointers and registers xyw_byte *ssp = &xyw_memory[SYSTEM_SSP]; xyw_byte *usp = &xyw_memory[SYSTEM_USP]; -xyw_byte *x = &xyw_memory[SYSTEM_X]; -xyw_byte *y = &xyw_memory[SYSTEM_Y]; +xyw_byte *x = 0x00; +xyw_byte *y = 0x00; + +//// 2-byte registers +xyw_word *pc = 0x00; +xyw_word *xw = 0x00; +xyw_word *yw = 0x00; //// Helpers to manage 2-byte values to memory (big-endian)

@@ -101,23 +101,11 @@ xyw_word val = mget(addr);

mset(addr, (xyw_word)(val + delta)); } -//// Helpers for common registers - -static inline xyw_word pc(void) { return mget(SYSTEM_PC); } -// static inline void pc_set(xyw_word val) { mset(SYSTEM_PC, val); } -// static inline void pc_add(int delta) { madd(SYSTEM_PC, delta); } -static inline xyw_word xw(void) { return mget(SYSTEM_XW); } -// static inline void xw_set(xyw_word val) { mset(SYSTEM_XW, val); } -// static inline void xw_add(int delta) { madd(SYSTEM_XW, delta); } -static inline xyw_word yw(void) { return mget(SYSTEM_YW); } -// static inline void yw_set(xyw_word val) { mset(SYSTEM_YW, val); } -// static inline void yw_add(int delta) { madd(SYSTEM_YW, delta); } - //// Mode helpers -static int is_x() { return xyw_memory[pc()] & XYW_MODE_X; } -static int is_y() { return xyw_memory[pc()] & XYW_MODE_Y; } -static int is_w() { return xyw_memory[pc()] & XYW_MODE_W; } +static int is_x() { return xyw_memory[*pc] & XYW_MODE_X; } +static int is_y() { return xyw_memory[*pc] & XYW_MODE_Y; } +static int is_w() { return xyw_memory[*pc] & XYW_MODE_W; } //// System stack management

@@ -174,176 +162,173 @@ //// Instructions

static void PSH() { - if (*usp > STACK_SIZE - 1) - { - xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_OVERFLOW; - return; - } - user_stack[(*usp)++] = xyw_memory[pc()]; + xyw_byte val = xyw_memory[(*pc)++]; + us_push(val); } static void PSHw() { - if (*usp > STACK_SIZE - 2) - { - xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_OVERFLOW; - return; - } - mset(USER_STACK_START + *usp, mget(pc())); - (*usp) += 2; + xyw_word val = mget((*pc)++); + us_pushw(val); + (*pc)++; } -static xyw_byte POP(xyw_byte first) +static void PSHx() { - // First operand, get value from X if set - if (first && is_x()) - { - return *x; - } - // Othwerwise try Y - if (first && is_y()) - { - return *y; - } - // For the second operand, get value from Y if both X and Y modes are set - if (!first && is_x() && is_y()) - { - return *y; - } - // If no mode is set, pop from stack + us_push(*x); +} + +static void PSHy() +{ + us_push(*y); +} + +static void PSHxw() +{ + us_pushw(*xw); +} + +static void PSHyw() +{ + us_pushw(*yw); +} + +static xyw_byte POP() +{ if (*usp < 1) { xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_UNDERFLOW; - return -1; + return; } - xyw_byte val = user_stack[*usp]; + xyw_byte val = user_stack[--(*usp)]; user_stack[*usp] = 0; - (*usp)--; return val; } -static xyw_word POPw(xyw_byte first) +static xyw_word POPw() { - // First operand, get value from X if set - if (first && is_x()) - { - return xw(); - } - // Othwerwise try Y - if (first && is_y()) - { - return yw(); - } - // For the second operand, get value from Y if both X and Y modes are set - if (!first && is_x() && is_y()) - { - return yw(); - } - // If no mode is set, pop from stack if (*usp < 2) { xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_UNDERFLOW; - return -1; + return; } - xyw_word val = mget(USER_STACK_START + (*usp) - 1); - mset(USER_STACK_START + (*usp) - 1, 0); + xyw_word val = mget(USER_STACK_START + (*usp) - 2); + mset(USER_STACK_START + (*usp) - 2, 0); (*usp) -= 2; return val; } -static xyw_byte LDR(xyw_word addr) +static void POPx() { - return xyw_memory[addr]; + if (*usp < 1) + { + xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_UNDERFLOW; + return; + } + *x = user_stack[--(*usp)]; + user_stack[*usp] = 0; } -static xyw_word LDRw(xyw_word addr) +static void POPy() { - return mget(addr); + if (*usp < 1) + { + xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_UNDERFLOW; + return; + } + *y = user_stack[--(*usp)]; + user_stack[*usp] = 0; } -static xyw_byte LDP(xyw_byte addr) +static void POPxw() { - return xyw_memory[((xyw_word)xyw_memory[SYSTEM_PAGE] << 8) | addr]; + if (*usp < 2) + { + xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_UNDERFLOW; + return; + } + *xw = mget(USER_STACK_START + (*usp) - 2); + mset(USER_STACK_START + (*usp) - 2, 0); + (*usp) -= 2; } -static xyw_word LDPw(xyw_byte addr) +static void POPyw() { - return mget(((xyw_word)xyw_memory[SYSTEM_PAGE] << 8) | addr); + if (*usp < 2) + { + xyw_memory[SYSTEM_ERROR] = XYW_ERROR_STACK_UNDERFLOW; + return; + } + *yw = mget(USER_STACK_START + (*usp) - 2); + mset(USER_STACK_START + (*usp) - 2, 0); + (*usp) -= 2; } -static xyw_byte ILD(xyw_word addr) +static void LDRx() { - madd(addr, 1); - return xyw_memory[mget(addr)]; + *x = POP(); + us_push(xyw_memory[*x]); } -static xyw_word ILDw(xyw_word addr) +static void LDRy() { - madd(addr, 1); - return mget(mget(addr)); + *y = POP(); + us_push(xyw_memory[*y]); } -static xyw_byte LDI(xyw_word addr) +static void LDRxw() { - xyw_byte r = xyw_memory[addr]; - madd(addr, 1); - return r; + *xw = POPw(); + us_pushw(mget(*xw)); } -static xyw_word LDIw(xyw_word addr) +static void LDRyw() { - xyw_word r = mget(addr); - madd(addr, 1); - return r; + *yw = POPw(); + us_pushw(mget(*yw)); } -static xyw_byte DLD(xyw_word addr) +// Example: ADD +static void ADD() { - madd(addr, -1); - return xyw_memory[mget(addr)]; + us_push(POP() + POP()); } -static xyw_word DLDw(xyw_word addr) +static void ADDw() { - madd(addr, -1); - return mget(mget(addr)); + us_pushw(POPw() + POPw()); } -static xyw_byte LDD(xyw_word addr) +static void ADDx() { - xyw_byte r = xyw_memory[addr]; - madd(addr, -1); - return r; + us_push(*x + POP()); } - -static xyw_word LDDw(xyw_word addr) +static void ADDy() { - xyw_word r = mget(addr); - madd(addr, -1); - return r; + us_push(*y + POP()); } -static void STR(xyw_word addr, xyw_byte val) +static void ADDxw() { - xyw_memory[addr] = val; + us_pushw(*xw + POPw()); } -static void STRw(xyw_word addr, xyw_word val) +static void ADDyw() { - mset(addr, val); + us_pushw(*yw + POPw()); } -static void STP(xyw_byte addr, xyw_byte val) +static void ADDxy() { - xyw_memory[((xyw_word)xyw_memory[SYSTEM_PAGE] << 8) | addr] = val; + us_push(*x + *y); } -static void STPw(xyw_byte addr, xyw_word val) +static void ADDxyw() { - mset(((xyw_word)xyw_memory[SYSTEM_PAGE] << 8) | addr, val); + us_pushw(*xw + *yw); } -//// Macro helpers +//// TODO: Review Macro helpers & expansions // Infix operation #define IOP(op) is_w() ? us_pushw((POPw(1) op POPw(0))) : us_push((POP(1) op POP(0)))

@@ -357,9 +342,7 @@ {

xyw_word current; while (1) { - current = pc(); - madd(SYSTEM_PC, 1); - switch (xyw_memory[current]) + switch (xyw_memory[*pc]) { // clang-format off /* BRK */ case 0x00: break;

@@ -377,7 +360,14 @@ /* LDI */ case 0x09: is_w() ? UOP(LDI) : UOP(LDIw); break;

/* DLD */ case 0x0A: is_w() ? UOP(DLD) : UOP(DLDw); break; /* LDD */ case 0x0B: is_w() ? UOP(LDD) : UOP(LDDw); break; - /* ADD */ case 0x0C: IOP(+); break; + /* ADD */ case 0x0C: us_push(POP() + POP()); break; + case XYW_MODE_X|0x0C: us_push(*x + POP()); break; + case XYW_MODE_Y|0x0C: us_push(*y + POP()); break; + case XYW_MODE_W|0x0C: us_pushw(POPw() + POPw()); break; + case XYW_MODE_X|XYW_MODE_W|0x0C: us_pushw(*xw + POPw()); break; + case XYW_MODE_Y|XYW_MODE_W|0x0C: us_pushw(*yw + POPw()); break; + case XYW_MODE_X|XYW_MODE_Y|0x0C: us_push(*x + *y); break; + case XYW_MODE_X|XYW_MODE_Y|XYW_MODE_W|0x0C: us_pushw(*xw + *yw); break; /* SUB */ case 0x0D: IOP(-); break; /* MUL */ case 0x0E: IOP(*); break; /* DIV */ case 0x0F: IOP(/); break;

@@ -403,6 +393,7 @@ /* JSR */ case 0x1E: break;

/* RTS */ case 0x1F: break; // clang-format on } + (*pc)++; } return 0;