From 1b77649e362331719466a1358551d80b08949e9f Mon Sep 17 00:00:00 2001 From: zongor Date: Mon, 19 Jan 2026 21:21:18 -0800 Subject: [PATCH] wip stack based --- arch/linux/tui/main.c | 79 ++------- vm/vm.c | 375 +++++++++--------------------------------- vm/vm.h | 227 +++++++++++-------------- 3 files changed, 185 insertions(+), 496 deletions(-) diff --git a/arch/linux/tui/main.c b/arch/linux/tui/main.c index 4ae1b74..5dc1c23 100644 --- a/arch/linux/tui/main.c +++ b/arch/linux/tui/main.c @@ -1,15 +1,13 @@ #include "../../../vm/vm.h" #include -#include #define CODE_SIZE 8192 #define MEMORY_SIZE 65536 u8 lmem[MEMORY_SIZE] = {0}; -u32 lcode[CODE_SIZE] = {0}; +u8 lcode[CODE_SIZE] = {0}; bool init_vm() { mem = lmem; - memset(mem, 0, MEMORY_SIZE*sizeof(u8)); code = lcode; lc = 0; mp = 0; @@ -52,77 +50,22 @@ u32 syscall(u32 id, u32 size, u32 mem_ptr) { } void test_add_two_num() { - i32 main_local_count = 5; - mp += (4 * main_local_count); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 1); - code[cp++] = ENCODE_B(OP_PUSH, 0, 0); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, 1); - code[cp++] = ENCODE_B(OP_PUSH, 1, 0); - i32 add = cp + 5; - code[cp++] = ENCODE_B(OP_LOAD_IMM, 2, add); - - code[cp++] = ENCODE_A(OP_CALL, 2, 3, 0); - code[cp++] = ENCODE_A(OP_INT_TO_STR, 4, 3, 0); - code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 4); - code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0); - + code[cp++] = OP_GET; + code[cp++] = OP_GET; + code[cp++] = OP_GET; + code[cp++] = OP_CALL; + code[cp++] = OP_INT_TO_STR; + code[cp++] = OP_SYSCALL; + code[cp++] = OP_HALT; /* add */ - code[cp++] = ENCODE_A(OP_ADD_INT, 2, 1, 0); - code[cp++] = ENCODE_B(OP_RETURN, 2, 0); -} - -void test_fibonacci() { - i32 fib = 7; - i32 base_case = 21; - /* function main() */ - i32 main_local_count = 4; - mp += (4 * main_local_count); - /* fib(35) */ - code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 35); - code[cp++] = ENCODE_B(OP_PUSH, 0, 0); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, fib); - code[cp++] = ENCODE_A(OP_CALL, 1, 9, 2); - /* print */ - code[cp++] = ENCODE_A(OP_INT_TO_STR, 3, 2, 0); - code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 3); - code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0); - /* function fib (int n) int */ - //code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_DBG_PRINT, 1, 0); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 8, fib); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, 2); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 2, base_case); - code[cp++] = ENCODE_A(OP_JLT_INT, 2, 0, 1); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 3, 2); - code[cp++] = ENCODE_A(OP_SUB_INT, 4, 0, 3); - code[cp++] = ENCODE_B(OP_PUSH, 4, 0); - code[cp++] = ENCODE_A(OP_CALL, 8, 9, 5); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 3, 1); - code[cp++] = ENCODE_A(OP_SUB_INT, 4, 0, 3); - code[cp++] = ENCODE_B(OP_PUSH, 4, 0); - code[cp++] = ENCODE_A(OP_CALL, 8, 9, 6); - code[cp++] = ENCODE_A(OP_ADD_INT, 7, 6, 5); - code[cp++] = ENCODE_B(OP_RETURN, 7, 0); - code[cp++] = ENCODE_B(OP_RETURN, 0, 0); -} - -void test_hello() { - u32 hello =str_alloc("nuqneH 'u'?", 12); - u32 new_line = str_alloc("\n", 1); - fp = mp; - /* function main() */ - i32 main_local_count = 3; - mp += (4 * main_local_count); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, hello); - code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 12, 0); - code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, new_line); - code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 0); - code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0); + code[cp++] = OP_ADD_INT; + code[cp++] = OP_RETURN; } i32 main() { init_vm(); - test_hello(); + test_add_two_num(); while(step_vm()) { // do stuff diff --git a/vm/vm.c b/vm/vm.c index 8dcfb26..6ce6f46 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -1,15 +1,16 @@ #include "vm.h" #define FRAME_HEADER_SIZE 12 -u32 pc; /* program counter */ -u32 cp; /* code pointer */ -u32 mp; /* memory pointer */ -u32 fp; /* frame pointer */ -u8 lc; /* child local count */ -u8 status; /* status flag */ -u8 interrupt; /* device interrupt */ -u32 *code; /* code */ -u8 *mem; /* memory */ +u32 pc; /* program counter */ +u32 cp; /* code pointer */ +u32 mp; /* memory pointer */ +u32 fp; /* frame pointer */ +u32 sp; /* frame pointer */ +u8 status; /* status flag */ +u8 interrupt; /* device interrupt */ +u32 *stack; /* stack */ +u8 *code; /* code */ +u8 *mem; /* memory */ #define MAX_LEN_INT32 11 #define MAX_INT32 2147483647 @@ -28,8 +29,8 @@ u32 str_alloc(char *str, u32 length) { } bool step_vm() { - u32 instruction = code[pc++]; - u8 opcode = DECODE_OP(instruction); + + u8 opcode = code[pc++]; u32 *locals = (u32*)(&mem[fp]); u32 *globals = (u32*)(mem); @@ -39,9 +40,9 @@ bool step_vm() { return false; } case OP_CALL: { - DECODE_A(instruction) + /* TODO: Fix this one so it makes sense with a stack based system */ /* function to jump to */ - u32 fn_ptr = locals[dest]; + u32 fn_ptr = stack[--sp]; /* get mp in 'global indexing mode' */ u32 *header = &globals[mp / 4]; /* reset child locals counter */ @@ -49,25 +50,22 @@ bool step_vm() { /* push parents frame value to reset the heap to */ (*header++) = fp; /* push return address to child frame */ - (*header++) = pc; - /* push local address to return the value to */ - (*header++) = fp + (src2 * 4); + globals[gmp + 1] = pc; /* increase the mp to new size */ mp += FRAME_HEADER_SIZE; /* now set the frame pointer, where the locals start */ fp = mp; /* move mp forward by count many locals */ - mp += (src1 * 4); + mp += stack[--sp]; /* jump to dest_ptr */ pc = fn_ptr; return true; } case OP_RETURN: { - DECODE_B(instruction) - u32 size = 0; - u32 return_value = locals[dest]; - bool is_ptr = (((u32)(1)) << 15) & imm; - bool replaces_value = (((u32)(1)) << 14) & imm; + /* TODO: Fix this one so it makes sense with a stack based system */ + u32 i, size = 0; + u32 return_value = stack[--sp]; + bool is_ptr = (((u32)(1)) << 15) & return_value; /* reset mp to saved mp, use header size to get "real" start of frame */ u32 *frame_start = &globals[(fp / 4) - 3]; @@ -75,7 +73,6 @@ bool step_vm() { u32 return_address = *frame_start++; u32 parent_local_return_address = *frame_start++; - USED(replaces_value); /* reset memory to parents end of memory */ mp = fp - FRAME_HEADER_SIZE; /* reset the frame pointer */ @@ -99,150 +96,24 @@ bool step_vm() { return true; } case OP_SYSCALL: { - DECODE_A(instruction) - u32 id = dest; /* syscall id */ - u32 size = src1; /* size of heap at that pointer */ - u32 rd = locals[src2]; /* the pointer */ + u32 id = stack[--sp]; /* syscall id */ + u32 size = stack[--sp]; /* size of heap at that pointer */ + u32 rd = stack[--sp]; /* the pointer */ status = syscall(id, size, rd); return true; } - case OP_PUSH: { - DECODE_B(instruction) - USED(imm); - globals[(mp / 4) + lc + 3] = locals[dest]; - lc++; - return true; - } - case OP_POP: { - DECODE_B(instruction) - USED(dest); - USED(imm); - mp -= 4; - lc--; - return true; - } - case OP_LOAD_IMM: { - DECODE_B(instruction) - locals[dest] = imm; - return true; - } - case OP_LOAD_UPPER_IMM: { - DECODE_B(instruction) - u32 value = locals[dest]; - locals[dest] = (value | (((u32)(imm)) << 16)); - return true; - } - case OP_LOAD_IND_8: { - DECODE_A(instruction) - USED(src2); - locals[dest] = READ_U8(locals[src1]); - return true; - } - case OP_LOAD_IND_16: { - DECODE_A(instruction) - USED(src2); - locals[dest] = READ_U16(locals[src1]); - return true; - } - case OP_LOAD_IND_32: { - DECODE_A(instruction) - USED(src2); - locals[dest] = READ_U32(locals[src1]); - return true; - } - case OP_LOAD_ABS_8: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_LOAD_ABS_16: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_LOAD_ABS_32: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_LOAD_OFF_8: { - DECODE_A(instruction) - locals[dest] = READ_U8((locals[src1] + locals[src2])); - return true; - } - case OP_LOAD_OFF_16: { - DECODE_A(instruction) - locals[dest] = READ_U16((locals[src1] + locals[src2])); - return true; - } - case OP_LOAD_OFF_32: { - DECODE_A(instruction) - locals[dest] = READ_U32((locals[src1] + locals[src2])); - return true; - } - case OP_STORE_ABS_8: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_STORE_ABS_16: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_STORE_ABS_32: { - /* need multibyte for this, ignore for now */ - status = 250; - return false; - } - case OP_STORE_IND_8: { - DECODE_A(instruction) - USED(src2); - WRITE_U8(locals[dest], locals[src1]); - return true; - } - case OP_STORE_IND_16: { - DECODE_A(instruction) - USED(src2); - WRITE_U16(locals[dest], locals[src1]); - return true; - } - case OP_STORE_IND_32: { - DECODE_A(instruction) - USED(src2); - WRITE_U32(locals[dest], locals[src1]); - return true; - } - case OP_STORE_OFF_8: { - DECODE_A(instruction) - WRITE_U8((locals[dest] + locals[src2]), locals[src1]); - return true; - } - case OP_STORE_OFF_16: { - DECODE_A(instruction) - WRITE_U16((locals[dest] + locals[src2]), locals[src1]); - return true; - } - case OP_STORE_OFF_32: { - DECODE_A(instruction) - WRITE_U32((locals[dest] + locals[src2]), locals[src1]); - return true; - } case OP_MEM_ALLOC: { - DECODE_A(instruction) - u32 size = locals[src1]; - locals[dest] = mp; + u32 size = stack[--sp]; + stack[sp++] = mp; WRITE_U32(mp, size); - USED(src2); mp += (size + 4); return true; } case OP_MEM_CPY_8: { - DECODE_A(instruction) u32 i = 0; - u32 mdest = locals[dest]; - u32 msrc = locals[src1]; - u32 count = locals[src2]; + u32 count = stack[--sp]; + u32 msrc = stack[--sp]; + u32 mdest = stack[--sp]; if (mdest + count >= mp) { status = 1; @@ -257,11 +128,10 @@ bool step_vm() { return true; } case OP_MEM_CPY_16: { - DECODE_A(instruction) u32 i = 0; - u32 mdest = locals[dest]; - u32 msrc = locals[src1]; - u32 count = locals[src2] * 2; + u32 count = stack[--sp]; + u32 msrc = stack[--sp]; + u32 mdest = stack[--sp]; if (mdest + count >= mp) { status = 1; @@ -277,11 +147,10 @@ bool step_vm() { return true; } case OP_MEM_CPY_32: { - DECODE_A(instruction) u32 i = 0; - u32 mdest = locals[dest]; - u32 msrc = locals[src1]; - u32 count = locals[src2]; + u32 count = stack[--sp]; + u32 msrc = stack[--sp]; + u32 mdest = stack[--sp]; if (mdest + count >= mp) { status = 1; @@ -296,25 +165,13 @@ bool step_vm() { return true; } case OP_MEM_SET_8: { - DECODE_A(instruction) u32 i, start, end; - - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - u32 r2 = fp + (src2 * 4); - - u8 value = (u8)READ_U32(r1); - u32 count = READ_U32(r2); - - if (r2 == 0) { - status = 1; - return true; - } - - start = READ_U32(rd); + u8 value = (u8)stack[--sp]; + u32 count = stack[--sp]; + start = stack[--sp]; end = start + count; - if (start >= mp || r2 > mp || end > mp) { + if (start >= mp || end > mp) { status = 1; return true; } @@ -327,25 +184,13 @@ bool step_vm() { return true; } case OP_MEM_SET_16: { - DECODE_A(instruction) u32 i, start, end; - - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - u32 r2 = fp + (src2 * 4); - - u16 value = (u16)READ_U32(r1); - u32 count = READ_U32(r2); - - if (r2 == 0) { - status = 1; - return true; - } - - start = READ_U32(rd); + u8 value = (u8)stack[--sp]; + u32 count = stack[--sp]; + start = stack[--sp]; end = start + count; - if (start >= mp || r2 > mp || end > mp) { + if (start >= mp || end > mp) { status = 1; return true; } @@ -358,21 +203,13 @@ bool step_vm() { return true; } case OP_MEM_SET_32: { - DECODE_A(instruction) u32 i, start, end; - - u32 value = locals[src1]; - u32 count = locals[src2]; - - if (count == 0) { - status = 1; - return true; - } - - start = READ_U32(locals[dest]); + u8 value = (u8)stack[--sp]; + u32 count = stack[--sp]; + start = stack[--sp]; end = start + count; - if (start >= mp || count > mp || end > mp) { + if (start >= mp || end > mp) { status = 1; return true; } @@ -384,12 +221,6 @@ bool step_vm() { status = 0; return true; } - case OP_MOV: { - DECODE_A(instruction) - USED(src2); - locals[dest] = locals[src1]; - return true; - } case OP_ADD_INT: { MATH_OP(i32, +); } @@ -421,27 +252,27 @@ bool step_vm() { MATH_OP(i32, -); } case OP_MUL_REAL: { - DECODE_A(instruction) + i32 src1 = (i32)stack[--sp]; + i32 src2 = (i32)stack[--sp]; - i32 src1_whole = (i32)locals[src1] >> 16; - i32 src2_whole = (i32)locals[src2] >> 16; + i32 src1_whole = src1 >> 16; + i32 src2_whole = src2 >> 16; - i32 src1_decimal = (i32)locals[src1] & 16; - i32 src2_decimal = (i32)locals[src2] & 16; + i32 src1_decimal = src1 & 16; + i32 src2_decimal = src2 & 16; i32 result = 0; result += (src1_whole * src2_whole) << 16; result += (src1_whole * src2_decimal); result += (src1_decimal * src2_whole); result += ((src1_decimal * src2_decimal) >> 16) & 16; - locals[dest] = result; + stack[sp++] = result; return true; } case OP_DIV_REAL: { - DECODE_A(instruction) i32 result; - i32 src1_val = (i32)locals[src1]; - i32 src2_val = (i32)locals[src2]; + i32 src1_val = (i32)stack[--sp]; + i32 src2_val = (i32)stack[--sp]; u32 src2_reciprocal = 1; src2_reciprocal <<= 31; @@ -450,49 +281,37 @@ bool step_vm() { result = src1_val * src2_reciprocal; result <<= 1; - locals[dest] = result; + stack[sp++] = result; return true; } case OP_INT_TO_REAL: { - DECODE_A(instruction) - i32 result = (i32)locals[src1] << 16; - USED(src2); - locals[dest] = result; + i32 result = (i32)stack[--sp] << 16; + stack[sp++] = result; return true; } case OP_INT_TO_NAT: { - DECODE_A(instruction) - u32 result = (u32)locals[src1]; - USED(src2); - locals[dest] = result; + u32 result = (u32)stack[--sp]; + stack[sp++] = result; return true; } case OP_NAT_TO_REAL: { - DECODE_A(instruction) - i32 result = (i32)locals[src1] << 16; - USED(src2); - locals[dest] = result; + i32 result = (i32)stack[--sp] << 16; + stack[sp++] = result; return true; } case OP_NAT_TO_INT: { - DECODE_A(instruction) - i32 result = (i32)locals[src1]; - USED(src2); - locals[dest] = result; + i32 result = (i32)stack[--sp]; + stack[sp++] = result; return true; } case OP_REAL_TO_INT: { - DECODE_A(instruction) - i32 result = (i32)locals[src1] >> 16; - USED(src2); - locals[dest] = result; + i32 result = (i32)stack[--sp] >> 16; + stack[sp++] = result; return true; } case OP_REAL_TO_NAT: { - DECODE_A(instruction) - u32 result = (u32)locals[src1] >> 16; - USED(src2); - locals[dest] = result; + u32 result = (u32)stack[--sp] >> 16; + stack[sp++] = result; return true; } case OP_BIT_SHIFT_LEFT: { @@ -513,49 +332,23 @@ bool step_vm() { case OP_BIT_XOR: { MATH_OP_NO_CAST(^); } - case OP_JMP_IMM: { - u32 imm = (((u32)code[(pc) + 3] << 24) | - ((u32)code[(pc) + 2] << 16) | - ((u32)code[(pc) + 1] << 8) | - ((u32)code[(pc)])); - pc = imm; - return true; - } - case OP_JMP_ABS: { - DECODE_A(instruction) - u32 jmp_dest = locals[dest]; + case OP_JMP: { + u32 jmp_dest = stack[--sp]; if (jmp_dest > cp) { status = 1; return true; } - USED(src1); - USED(src2); - - pc = jmp_dest; - return true; - } - case OP_JMP_OFF: { - DECODE_A(instruction) - u32 jmp_dest = locals[dest] + locals[src1]; - if (jmp_dest > cp) { - status = 1; - return true; - } - USED(src2); pc = jmp_dest; return true; } case OP_JMP_FLAG: { - DECODE_A(instruction) u32 mask; - u32 jmp_dest = locals[dest]; + u32 jmp_dest = stack[--sp]; if (jmp_dest > cp) { status = 1; return true; } - USED(src1); - USED(src2); mask = -(u32)(status == 0); pc = (jmp_dest & mask) | (pc & ~mask); @@ -615,16 +408,13 @@ bool step_vm() { case OP_JLE_REAL: { COMPARE_AND_JUMP(i32, <=); } - case OP_INT_TO_STR: { - DECODE_A(instruction) - + case OP_INT_TO_STR: { u32 i = MAX_LEN_INT32; - i32 v = (i32)locals[src1]; + i32 v = (i32)stack[--sp]; char buffer[MAX_LEN_INT32]; i32 n = v; bool neg = n < 0; - USED(src2); - + if (neg) n = -n; @@ -639,18 +429,16 @@ bool step_vm() { buffer[--i] = '0'; /* Copy from buffer[i] to buffer + MAX_LEN_INT32 */ - locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i); + stack[sp++] = str_alloc(buffer + i, MAX_LEN_INT32 - i); return pc; } case OP_NAT_TO_STR: { - DECODE_A(instruction) - - u32 v = (i32)locals[src1]; + u32 v = (i32)stack[--sp]; char buffer[MAX_LEN_INT32]; u32 n = v; u32 i = MAX_LEN_INT32; - USED(src2); + do { buffer[--i] = radix_set[n % 10]; n /= 10; @@ -659,15 +447,13 @@ bool step_vm() { if (v == 0) buffer[--i] = '0'; /* Copy from buffer[i] to buffer + MAX_LEN_INT32 */ - locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i); + stack[sp++] = str_alloc(buffer + i, MAX_LEN_INT32 - i); return pc; } case OP_REAL_TO_STR: { - DECODE_A(instruction) - u32 i = 0, j = 0; - i32 q = (i32)locals[src1]; + i32 q = (i32)stack[--sp]; char buffer[MAX_LEN_INT32]; u32 int_part, frac_part; @@ -678,7 +464,6 @@ bool step_vm() { int_part = q >> 16; frac_part = q & 0xFFFF; - USED(src2); if (int_part == 0) { buffer[i++] = radix_set[0]; @@ -701,7 +486,7 @@ bool step_vm() { frac_part &= 0xFFFF; } - locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i); + stack[sp++] = str_alloc(buffer + i, MAX_LEN_INT32 - i); return pc; } diff --git a/vm/vm.h b/vm/vm.h index 9300dc4..b4c336f 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -3,121 +3,77 @@ #include "libc.h" -/** - * Instruction Types - * - * A : [8:opcode][8:dest][8:src1][8:src2] - * B : [8:opcode][8:dest][16:immediate] - * C : [8:opcode][24:immediate] - */ -#define DECODE_OP(instruction) ((((u32)(instruction)) >> 24) & 0xFF) - -#define ENCODE_A(opcode, dest, src1, src2) ((((u32)(opcode) & 0xFF) << 24) | \ - (((u32)(dest) & 0xFF) << 16) | \ - (((u32)(src1) & 0xFF) << 8) | \ - (((u32)(src2) & 0xFF))) - -#define DECODE_A(instruction) \ - u8 dest = (((u32)(instruction)) >> 16) & 0xFF; \ - u8 src1 = (((u32)(instruction)) >> 8) & 0xFF; \ - u8 src2 = ((u32)(instruction)) & 0xFF; - -#define ENCODE_B(opcode, dest, imm) ((((u32)(opcode) & 0xFF) << 24) | \ - (((u32)(dest) & 0xFF) << 16) | \ - (((u32)(imm)) & 0xFFFF)) -#define DECODE_B(instruction) \ - u8 dest = (((u32)(instruction)) >> 16) & 0xFF; \ - u16 imm = ((u32)(instruction)) & 0xFFFF; - -#define ENCODE_C(opcode, imm) ((((u32)(opcode) & 0xFF) << 24) | \ - (((u32)(imm)) & 0xFFFFFF)) -#define DECODE_C(instruction) \ - u32 imm = ((u32)(instruction)) & 0xFFFFFF; - typedef enum { - OP_HALT, /* halt : A : all zeros : halt execution */ - OP_CALL, /* call : A : dest args return : creates a new frame */ - OP_RETURN, /* return : B : dest return_flags: returns from a frame to the parent frame */ - OP_SYSCALL, /* syscall : A : id args mem_ptr : does a system call based on id with args */ - OP_LOAD_IMM, /* load_immediate : B : locals[dest] = const as u16 */ - OP_LOAD_UPPER_IMM, /* load_upper_immediate : B : locals[dest] = const as u32 << 16 | u16 */ - OP_LOAD_IND_8, /* load_indirect_8 : A : locals[dest] = memory[locals[src1]] as u8 */ - OP_LOAD_IND_16, /* load_indirect_16 : A : locals[dest] = memory[locals[src1]] as u16 */ - OP_LOAD_IND_32, /* load_indirect_32 : A : locals[dest] = memory[locals[src1]] as u32 */ - OP_LOAD_ABS_8, /* load_absolute_8 : E : locals[dest] = memory[src1:u32] as u8 */ - OP_LOAD_ABS_16, /* load_absolute_16 : E : locals[dest] = memory[src1:u32] as u16 */ - OP_LOAD_ABS_32, /* load_absolute_32 : E : locals[dest] = memory[src1:u32] as u32 */ - OP_LOAD_OFF_8, /* load_offset_8 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u8 */ - OP_LOAD_OFF_16, /* load_offset_16 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u16 */ - OP_LOAD_OFF_32, /* load_offset_32 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u32 */ - OP_STORE_ABS_8, /* store_absolute_8 : E : memory[dest] = src1 && 0xFF */ - OP_STORE_ABS_16, /* store_absolute_16 : E : memory[dest] = src1 && 0xFFFF */ - OP_STORE_ABS_32, /* store_absolute_32 : E : memory[dest] = src1 */ - OP_STORE_IND_8, /* store_indirect_8 : A : memory[locals[dest]] = locals[src1] && 0xFF */ - OP_STORE_IND_16, /* store_indirect_16 : A : memory[locals[dest]] = locals[src1] && 0xFFFF*/ - OP_STORE_IND_32, /* store_indirect_32 : A : memory[locals[dest]] = locals[src1] */ - OP_STORE_OFF_8, /* store_offset_8 : A : memory[locals[dest] + locals[src2]] = locals[src1] && 0xFF */ - OP_STORE_OFF_16, /* store_offset_16 : A : memory[locals[dest] + locals[src2]] = locals[src1] && 0xFFFF */ - OP_STORE_OFF_32, /* store_offset_32 : A : memory[locals[dest] + locals[src2]] = locals[src1] */ - OP_MEM_ALLOC, /* alloc : A : memory[dest] = [locals[src1] as size + 4] */ - OP_MEM_CPY_8, /* memcpy_8 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */ - OP_MEM_CPY_16, /* memcpy_16 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */ - OP_MEM_CPY_32, /* memcpy_32 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */ - OP_MEM_SET_8, /* memset_8 : A : memory[dest..dest+src2] = local[src1] as u8 */ - OP_MEM_SET_16, /* memset_16 : A : memory[dest..dest+src2] = local[src1] as u16 */ - OP_MEM_SET_32, /* memset_32 : A : memory[dest..dest+src2] = local[src1] as u32 */ - OP_MOV, /* mov : A : locals[dest] = locals[src1] */ - OP_PUSH, /* push : B : push u32 value onto the childs locals */ - OP_POP, /* pop : C : pop u32 value off the stack (move MP back) */ - OP_ADD_INT, /* add_int : A : locals[dest] = locals[src1] + locals[src2] */ - OP_SUB_INT, /* sub_int : A : locals[dest] = locals[src1] - locals[src2] */ - OP_MUL_INT, /* mul_int : A : locals[dest] = locals[src1] * locals[src2] */ - OP_DIV_INT, /* div_int : A : locals[dest] = locals[src1] / locals[src2] */ - OP_ADD_NAT, /* add_nat : A : locals[dest] = locals[src1] + locals[src2] */ - OP_SUB_NAT, /* sub_nat : A : locals[dest] = locals[src1] - locals[src2] */ - OP_MUL_NAT, /* mul_nat : A : locals[dest] = locals[src1] * locals[src2] */ - OP_DIV_NAT, /* div_nat : A : locals[dest] = locals[src1] / locals[src2] */ - OP_ADD_REAL, /* add_real : A : locals[dest] = locals[src1] + locals[src2] */ - OP_SUB_REAL, /* sub_real : A : locals[dest] = locals[src1] - locals[src2] */ - OP_MUL_REAL, /* mul_real : A : locals[dest] = locals[src1] * locals[src2] */ - OP_DIV_REAL, /* div_real : A : locals[dest] = locals[src1] / locals[src2] */ - OP_INT_TO_REAL, /* int_to_real : A : locals[dest] = locals[src1] as real */ - OP_INT_TO_NAT, /* int_to_nat : A : locals[dest] = locals[src1] as nat */ - OP_NAT_TO_REAL, /* nat_to_real : A : locals[dest] = locals[src1] as real */ - OP_NAT_TO_INT, /* nat_to_int : A : locals[dest] = locals[src1] as int */ - OP_REAL_TO_INT, /* real_to_int : A : locals[dest] = locals[src1] as int */ - OP_REAL_TO_NAT, /* real_to_nat : A : locals[dest] = locals[src1] as nat */ - OP_BIT_SHIFT_LEFT, /* bit_shift_left : A : locals[dest] = locals[src1] << locals[src2] */ - OP_BIT_SHIFT_RIGHT,/* bit_shift_right : A : locals[dest] = locals[src1] >> locals[src2] */ - OP_BIT_SHIFT_R_EXT,/* bit_shift_r_ext : A : locals[dest] as i32 = locals[src1] >> locals[src2] */ - OP_BIT_AND, /* bit_and : A : locals[dest] = locals[src1] & locals[src2] */ - OP_BIT_OR, /* bit_or : A : locals[dest] = locals[src1] | locals[src2] */ - OP_BIT_XOR, /* bit_xor : A : locals[dest] = locals[src1] ^ locals[src2] */ - OP_JMP_IMM, /* jump_immediate : E : jump to imm unconditionally */ - OP_JMP_ABS, /* jump_absolute : A : jump to locals[dest] unconditionally */ - OP_JMP_OFF, /* jump_offset : A : jump to locals[dest] + locals[src1] unconditionally */ - OP_JMP_FLAG, /* jump_if_flag : A : jump to locals[dest] if flag > 0 */ - OP_JEQ_INT, /* jump_eq_int : A : jump to locals[dest] if locals[src1] as int == locals[src2] as int */ - OP_JNE_INT, /* jump_neq_int : A : jump to locals[dest] if locals[src1] as int != locals[src2] as int */ - OP_JGT_INT, /* jump_gt_int : A : jump to locals[dest] if locals[src1] as int > locals[src2] as int */ - OP_JLT_INT, /* jump_lt_int : A : jump to locals[dest] if locals[src1] as int < locals[src2] as int */ - OP_JLE_INT, /* jump_le_int : A : jump to locals[dest] if locals[src1] as int <= locals[src2] as int */ - OP_JGE_INT, /* jump_ge_int : A : jump to locals[dest] if locals[src1] as int >= locals[src2] as int */ - OP_JEQ_NAT, /* jump_eq_nat : A : jump to locals[dest] if locals[src1] as nat == locals[src2] as nat */ - OP_JNE_NAT, /* jump_neq_nat : A : jump to locals[dest] if locals[src1] as nat != locals[src2] as nat */ - OP_JGT_NAT, /* jump_gt_nat : A : jump to locals[dest] if locals[src1] as nat > locals[src2] as nat */ - OP_JLT_NAT, /* jump_lt_nat : A : jump to locals[dest] if locals[src1] as nat < locals[src2] as nat */ - OP_JLE_NAT, /* jump_le_nat : A : jump to locals[dest] if locals[src1] as nat <= locals[src2] as nat */ - OP_JGE_NAT, /* jump_ge_nat : A : jump to locals[dest] if locals[src1] as nat >= locals[src2] as nat */ - OP_JEQ_REAL, /* jump_eq_real : A : jump to locals[dest] if locals[src1] as real == locals[src2] as real */ - OP_JNE_REAL, /* jump_neq_real : A : jump to locals[dest] if locals[src1] as real != locals[src2] as real */ - OP_JGE_REAL, /* jump_ge_real : A : jump to locals[dest] if locals[src1] as real >= locals[src2] as real */ - OP_JGT_REAL, /* jump_gt_real : A : jump to locals[dest] if locals[src1] as real > locals[src2] as real */ - OP_JLT_REAL, /* jump_lt_real : A : jump to locals[dest] if locals[src1] as real < locals[src2] as real */ - OP_JLE_REAL, /* jump_le_real : A : jump to locals[dest] if locals[src1] as real <= locals[src2] as real */ - OP_INT_TO_STR, /* int_to_str : A : locals[dest] = &mem[mp..] locals[src1] as str */ - OP_NAT_TO_STR, /* nat_to_str : A : locals[dest] = &mem[mp..] locals[src1] as str */ - OP_REAL_TO_STR, /* real_to_str : A : locals[dest] = &mem[mp..] locals[src1] as str */ + OP_HALT, /* `halt` | halt execution */ + OP_CALL, /* ptr `call` | creates a new frame */ + OP_RETURN, /* `return` | returns from a frame to the parent frame */ + OP_SYSCALL, /* `syscall` | id args mem_ptr : does a system call based on id with args */ + OP_LOAD_8, /* &dest `load-8` u8 | push memory[obj1] onto stack as u8 */ + OP_LOAD_16, /* &dest `load-16` u16 | push memory[obj1] onto stack as u16 */ + OP_LOAD_32, /* &dest `load` u32 | push memory[obj1] onto stack as u32 */ + OP_STORE_8, /* &dest obj1 `store-8` - | memory[dest] = obj1 << 8 */ + OP_STORE_16, /* &dest obj1 `store-16`- | memory[dest] = obj1 << 16 */ + OP_STORE_32, /* &dest obj1 `store` - | memory[dest] = obj1 */ + OP_MALLOC, /* size `malloc` ptr | allocate 'size + 4' of memory and push ptr to memory on stack */ + OP_GET, /* &local `get` obj1 | get the value from the local slot */ + OP_SET, /* obj1 &local `set` - | set the value of the local slot */ + OP_MEM_ALLOC, /* size `alloc` ptr | allocate 'size + 4' of memory and push ptr to memory on stack */ + OP_MEM_CPY_8, /* `memcpy_8` | memory[src1..src1+src2] = memory[dest..dest+src2] */ + OP_MEM_CPY_16, /* `memcpy_16` | memory[src1..src1+src2] = memory[dest..dest+src2] */ + OP_MEM_CPY_32, /* `memcpy_32` | memory[src1..src1+src2] = memory[dest..dest+src2] */ + OP_MEM_SET_8, /* `memset_8` | memory[dest..dest+src2] = local[src1] as u8 */ + OP_MEM_SET_16, /* `memset_16` | memory[dest..dest+src2] = local[src1] as u16 */ + OP_MEM_SET_32, /* `memset_32` | memory[dest..dest+src2] = local[src1] as u32 */ + OP_ADD_INT, /* obj2 obj1 `add_int` obj | obj1 + obj2 then push result on stack */ + OP_SUB_INT, /* obj2 obj1 `sub_int` obj | obj1 - obj2 then push result on stack */ + OP_MUL_INT, /* obj2 obj1 `mul_int` obj | obj1 * obj2 then push result on stack */ + OP_DIV_INT, /* obj2 obj1 `div_int` obj | obj1 / obj2 then push result on stack */ + OP_ADD_NAT, /* obj2 obj1 `add_nat` obj | obj1 + obj2 then push result on stack */ + OP_SUB_NAT, /* obj2 obj1 `sub_nat` obj | obj1 - obj2 then push result on stack */ + OP_MUL_NAT, /* obj2 obj1 `mul_nat` obj | obj1 * obj2 then push result on stack */ + OP_DIV_NAT, /* obj2 obj1 `div_nat` obj | obj1 / obj2 then push result on stack */ + OP_ADD_REAL, /* obj2 obj1 `add_real` obj | obj1 + obj2 then push result on stack */ + OP_SUB_REAL, /* obj2 obj1 `sub_real` obj | obj1 - obj2 then push result on stack */ + OP_MUL_REAL, /* obj2 obj1 `mul_real` obj | obj1 * obj2 then push result on stack */ + OP_DIV_REAL, /* obj2 obj1 `div_real` obj | obj1 / obj2 then push result on stack */ + OP_INT_TO_REAL, /* obj1 `int_to_real` obj1 as real | casts an int to a fixed number */ + OP_INT_TO_NAT, /* obj1 `int_to_nat` obj1 as nat | casts an int to a unsigned int */ + OP_NAT_TO_REAL, /* obj1 `nat_to_real` obj1 as real | casts a unsigned int to a fixed number */ + OP_NAT_TO_INT, /* obj1 `nat_to_int` obj1 as int | casts a unsigned int to an int */ + OP_REAL_TO_INT, /* obj1 `real_to_int` obj1 as int | casts a fixed number to an int */ + OP_REAL_TO_NAT, /* obj1 `real_to_nat` obj1 as nat | casts a fixed number to an unsigned int */ + OP_BIT_SHIFT_LEFT, /* obj2 obj1 `bit_shift_left` obj | src1] << locals[src2] */ + OP_BIT_SHIFT_RIGHT,/* obj2 obj1 `bit_shift_right` obj | src1] >> locals[src2] */ + OP_BIT_SHIFT_R_EXT,/* obj2 obj1 `bit_shift_r_ext` obj | src1 >> src2 then cast result as i32 */ + OP_BIT_AND, /* obj2 obj1 `bit_and` obj | obj1 & obj2 */ + OP_BIT_OR, /* obj2 obj1 `bit_or` obj | obj1 | obj2 */ + OP_BIT_XOR, /* obj2 obj1 `bit_xor` obj | obj1 ^ obj2 */ + OP_JMP, /* pc `jump` | jump unconditionally */ + OP_JMP_FLAG, /* pc `jump_if_flag` | jump to pc if flag > 0 */ + OP_JEQ_INT, /* obj2 obj1 pc `jump_eq_int` | jump to pc if obj1 as int == obj2 as int */ + OP_JNE_INT, /* obj2 obj1 pc `jump_neq_int` | jump to pc if obj1 as int != obj2 as int */ + OP_JGT_INT, /* obj2 obj1 pc `jump_gt_int` | jump to pc if obj1 as int > obj2 as int */ + OP_JLT_INT, /* obj2 obj1 pc `jump_lt_int` | jump to pc if obj1 as int < obj2 as int */ + OP_JLE_INT, /* obj2 obj1 pc `jump_le_int` | jump to pc if obj1 as int <= obj2 as int */ + OP_JGE_INT, /* obj2 obj1 pc `jump_ge_int` | jump to pc if obj1 as int >= obj2 as int */ + OP_JEQ_NAT, /* obj2 obj1 pc `jump_eq_nat` | jump to pc if obj1 as nat == obj2 as nat */ + OP_JNE_NAT, /* obj2 obj1 pc `jump_neq_nat` | jump to pc if obj1 as nat != obj2 as nat */ + OP_JGT_NAT, /* obj2 obj1 pc `jump_gt_nat` | jump to pc if obj1 as nat > obj2 as nat */ + OP_JLT_NAT, /* obj2 obj1 pc `jump_lt_nat` | jump to pc if obj1 as nat < obj2 as nat */ + OP_JLE_NAT, /* obj2 obj1 pc `jump_le_nat` | jump to pc if obj1 as nat <= obj2 as nat */ + OP_JGE_NAT, /* obj2 obj1 pc `jump_ge_nat` | jump to pc if obj1 as nat >= obj2 as nat */ + OP_JEQ_REAL, /* obj2 obj1 pc `jump_eq_real` | jump to pc if obj1 as real == obj2 as real */ + OP_JNE_REAL, /* obj2 obj1 pc `jump_neq_real` | jump to pc if obj1 as real != obj2 as real */ + OP_JGE_REAL, /* obj2 obj1 pc `jump_ge_real` | jump to pc if obj1 as real >= obj2 as real */ + OP_JGT_REAL, /* obj2 obj1 pc `jump_gt_real` | jump to pc if obj1 as real > obj2 as real */ + OP_JLT_REAL, /* obj2 obj1 pc `jump_lt_real` | jump to pc if obj1 as real < obj2 as real */ + OP_JLE_REAL, /* obj2 obj1 pc `jump_le_real` | jump to pc if obj1 as real <= obj2 as real */ + OP_INT_TO_STR, /* obj1 `int-to-string` str_ptr | convert obj1 to str */ + OP_NAT_TO_STR, /* obj1 `nat-to-string` str_ptr | convert obj1 to str */ + OP_REAL_TO_STR, /* obj1 `real-to-string` str_ptr | convert obj1 to str */ + OP_STR_TO_INT, /* str_ptr `string-to-int` obj | convert obj1 to int */ + OP_STR_TO_NAT, /* str_ptr `string-to-nat` obj | convert obj1 to nat */ + OP_STR_TO_REAL, /* str_ptr `string-to-real` obj | convert obj1 to real */ OP_MAX_OPCODE /* not an opcode count of instructions */ } Opcode; @@ -131,10 +87,12 @@ extern u32 pc; /* program counter */ extern u32 cp; /* code pointer */ extern u32 mp; /* memory pointer */ extern u32 fp; /* frame pointer */ +extern u32 sp; /* stack pointer */ extern u8 lc; /* child local count */ extern u8 status; /* status flag */ extern u8 interrupt; /* device interrupt */ -extern u32 *code; /* code */ +extern u32 *stack; /* stack */ +extern u8 *code; /* code */ extern u8 *mem; /* memory */ #define READ_U8(addr) (mem[addr]) @@ -166,31 +124,34 @@ extern u8 *mem; /* memory */ mem[addr + 3] = ((value) >> 24) & 0xFF; \ } while (0) +#define COMPARE_AND_JUMP(type, op) \ + do { \ + i32 cond; \ + u32 mask, target; \ + type value; \ + type value2; \ + value2 = (type)stack[--sp]; \ + value = (type)stack[--sp]; \ + target = stack[--sp]; \ + cond = !!(value op value2); \ + mask = -(u32)cond; \ + pc = (target & mask) | (pc & ~mask); \ + return true; \ + } while (0) + #define MATH_OP(type, op) \ do { \ - DECODE_A(instruction) \ - locals[dest] = ((type)locals[src1] op (type)locals[src2]); \ + type b = (type)stack[--sp]; \ + type a = (type)stack[--sp]; \ + stack[sp++] = (type)(a op b); \ return true; \ } while (0) #define MATH_OP_NO_CAST(op) \ do { \ - DECODE_A(instruction) \ - locals[dest] = (locals[src1] op locals[src2]); \ - return true; \ - } while (0) - -#define COMPARE_AND_JUMP(type, op) \ - do { \ - DECODE_A(instruction) \ - i32 cond; \ - u32 mask; \ - u32 target = locals[dest]; \ - type value = (type)locals[src1]; \ - type value2 = (type)locals[src2]; \ - cond = !!(value op value2); \ - mask = -(u32)cond; \ - pc = (target & mask) | (pc & ~mask); \ + u32 a = stack[--sp]; \ + u32 b = stack[--sp]; \ + stack[sp++] = a op b; \ return true; \ } while (0)