diff --git a/arch/linux/gui/main.c b/arch/linux/gui/main.c index ff88bd1..7ecb7ea 100644 --- a/arch/linux/gui/main.c +++ b/arch/linux/gui/main.c @@ -1,17 +1,36 @@ #include "../../../vm/vm.h" #include #include +#include -int main() { - VM vm = {0}; +#define CODE_SIZE 8192 +#define MEMORY_SIZE 65536 +u8 lmem[MEMORY_SIZE] = {0}; +u32 lcode[CODE_SIZE] = {0}; +bool init_vm() { + mem = lmem; + memset(mem, 0, MEMORY_SIZE*sizeof(u8)); + code = lcode; + mp = 0; + cp = 0; + pc = 0; + interrupt = 0; + return true; +} + +u32 syscall(u32 id, u32 args, u32 mem_ptr) { + return 0; // success +} + +i32 main() { if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL initialization failed: %s\n", SDL_GetError()); return 1; } SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); - while(step_vm(&vm)) { + while(step_vm()) { // do stuff } diff --git a/arch/linux/tui/main.c b/arch/linux/tui/main.c index 85fd125..d14f507 100644 --- a/arch/linux/tui/main.c +++ b/arch/linux/tui/main.c @@ -1,10 +1,33 @@ #include "../../../vm/vm.h" #include +#include -int main() { - VM vm = {0}; +#define CODE_SIZE 8192 +#define MEMORY_SIZE 65536 +u8 lmem[MEMORY_SIZE] = {0}; +u32 lcode[CODE_SIZE] = {0}; - while(step_vm(&vm)) { +bool init_vm() { + mem = lmem; + memset(mem, 0, MEMORY_SIZE*sizeof(u8)); + code = lcode; + mp = 0; + cp = 0; + pc = 0; + interrupt = 0; + return true; +} + +u32 syscall(u32 id, u32 args, u32 mem_ptr) { + USED(id); + USED(args); + USED(mem_ptr); + return 0; // success +} + +i32 main() { + + while(step_vm()) { // do stuff } diff --git a/arch/web/gui/main.c b/arch/web/gui/main.c index 1113027..db8ebf9 100644 --- a/arch/web/gui/main.c +++ b/arch/web/gui/main.c @@ -4,20 +4,40 @@ #undef true #undef false +#include +#include #include #include #include -VM vm = {0}; +#define CODE_SIZE 8192 +#define MEMORY_SIZE 65536 +u8 lmem[MEMORY_SIZE] = {0}; +u32 lcode[CODE_SIZE] = {0}; + +bool init_vm() { + mem = lmem; + memset(mem, 0, MEMORY_SIZE*sizeof(u8)); + code = lcode; + mp = 0; + cp = 0; + pc = 0; + interrupt = 0; + return true; +} + +u32 syscall(u32 id, u32 args, u32 mem_ptr) { + return 0; // success +} void mainloop() { - if (!step_vm(&vm)) { + if (!step_vm()) { emscripten_cancel_main_loop(); return; } } -int main() { +i32 main() { if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL initialization failed: %s\n", SDL_GetError()); return 1; diff --git a/arch/web/gui/shell_minimal.html b/arch/web/gui/shell_minimal.html deleted file mode 100644 index 8a8c6db..0000000 --- a/arch/web/gui/shell_minimal.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - Emscripten-Generated Code - - - -
-
emscripten
-
Downloading...
-
- -
-
- -
-
-
- Resize canvas - Lock/hide mouse pointer -     - -
- -
- -
- - {{{ SCRIPT }}} - - \ No newline at end of file diff --git a/arch/web/tui/main.c b/arch/web/tui/main.c index 20b3ebd..b70ab7e 100644 --- a/arch/web/tui/main.c +++ b/arch/web/tui/main.c @@ -3,19 +3,38 @@ #undef false #include +#include #include #include -VM vm = {0}; +#define CODE_SIZE 8192 +#define MEMORY_SIZE 65536 +u8 lmem[MEMORY_SIZE] = {0}; +u32 lcode[CODE_SIZE] = {0}; + +bool init_vm() { + mem = lmem; + memset(mem, 0, MEMORY_SIZE*sizeof(u8)); + code = lcode; + mp = 0; + cp = 0; + pc = 0; + interrupt = 0; + return true; +} + +u32 syscall(u32 id, u32 args, u32 mem_ptr) { + return 0; // success +} void mainloop(void) { - if (!step_vm(&vm)) { + if (!step_vm()) { emscripten_cancel_main_loop(); return; } } -int main(void) { +i32 main(void) { printf("VM loaded successfully\n"); emscripten_set_main_loop(mainloop, 0, 1); diff --git a/arch/web/tui/shell_minimal.html b/arch/web/tui/shell_minimal.html deleted file mode 100644 index 8a8c6db..0000000 --- a/arch/web/tui/shell_minimal.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - Emscripten-Generated Code - - - -
-
emscripten
-
Downloading...
-
- -
-
- -
-
-
- Resize canvas - Lock/hide mouse pointer -     - -
- -
- -
- - {{{ SCRIPT }}} - - \ No newline at end of file diff --git a/build b/build index 3c8f8de..b53db51 100755 --- a/build +++ b/build @@ -81,7 +81,7 @@ case $UI in LINK_FLAGS="" ;; "emcc") - LINK_FLAGS="-s ASYNCIFY --shell-file $SRC_DIR/shell_minimal.html" + LINK_FLAGS="-s ASYNCIFY --shell-file $SRC_DIR/../shell_minimal.html" ;; esac ;; @@ -91,7 +91,7 @@ case $UI in LINK_FLAGS="$(sdl2-config --libs --cflags)" ;; "emcc") - LINK_FLAGS="-s USE_SDL=2 -s ASYNCIFY --shell-file $SRC_DIR/shell_minimal.html" + LINK_FLAGS="-s USE_SDL=2 -s ASYNCIFY --shell-file $SRC_DIR/../shell_minimal.html" ;; esac ;; diff --git a/vm/libc.h b/vm/libc.h index 89d702e..c8cbc42 100644 --- a/vm/libc.h +++ b/vm/libc.h @@ -22,6 +22,9 @@ typedef float f32; #define AS_INT(v) ((i32)(v)) #define AS_NAT(v) ((u32)(v)) +#define AS_REAL(v) ((i32)(v)) +#define FLOAT_TO_REAL(v) (((i32)(v)) * 65536.0f) +#define REAL_TO_FLOAT(v) (((f32)(v)) / 65536.0f) void mcpy(u8 *dest, const u8 *src, u32 n); i32 scpy(char* to, const char *from, u32 length); diff --git a/vm/vm.c b/vm/vm.c index f21cab7..f859f59 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -1,11 +1,13 @@ #include "vm.h" -u32 mp; /* memory pointer */ -u32 cp; /* code pointer */ -u32 pc; /* program counter */ -u32 flag; /* flag */ -u32 *code; /* code */ -u8 *mem; /* memory */ +u32 pc; /* program counter */ +u32 cp; /* code pointer */ +u32 mp; /* memory pointer */ +u32 fp; /* frame pointer */ +u32 flag; /* flag */ +u8 interrupt; /* device interrupt */ +u32 *code; /* code */ +u8 *mem; /* memory */ bool step_vm() { @@ -14,18 +16,32 @@ bool step_vm() { switch (opcode) { case OP_HALT: { + /* no need to decode, all are zeros */ return false; } case OP_CALL: { - } case OP_RETURN: { } case OP_SYSCALL: { + DECODE_A(instruction) + u32 id = fp + dest; + u32 args = fp + src1; + u32 mem_ptr = fp + src2; + flag = syscall(id, args, mem_ptr); + return true; } case OP_LOAD_IMM: { + DECODE_B(instruction) + u32 rd = fp + dest; + mem[rd] = imm; + return true; } case OP_LOAD_UPPER_IMM: { + DECODE_B(instruction) + u32 rd = fp + dest; + mem[rd] = (mem[rd] | (((u32)(imm)) << 16)); + return true; } case OP_LOAD_IND_8: { } @@ -76,52 +92,121 @@ bool step_vm() { case OP_REG_MOV: { } case OP_ADD_INT: { + MATH_OP(i32, +); } case OP_SUB_INT: { + MATH_OP(i32, -); } case OP_MUL_INT: { + MATH_OP(i32, *); } case OP_DIV_INT: { - } - case OP_ABS_INT: { - } - case OP_NEG_INT: { + MATH_OP(i32, /); } case OP_ADD_NAT: { + MATH_OP(u32, +); } case OP_SUB_NAT: { + MATH_OP(u32, -); } case OP_MUL_NAT: { + MATH_OP(u32, *); } case OP_DIV_NAT: { - } - case OP_ABS_NAT: { - } - case OP_NEG_NAT: { + MATH_OP(u32, /); } case OP_ADD_REAL: { + MATH_OP(i32, +); } case OP_SUB_REAL: { + MATH_OP(i32, -); } case OP_MUL_REAL: { + DECODE_A(instruction) + u32 rd = fp + dest; + u32 r1 = fp + src1; + u32 r2 = fp + src2; + + i32 src1_whole = (i32)mem[r1] >> 16; + i32 src2_whole = (i32)mem[r2] >> 16; + + i32 src1_decimal = (i32)mem[r1] & 16; + i32 src2_decimal = (i32)mem[r2] & 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; + mem[rd] = result; + return true; } case OP_DIV_REAL: { - } - case OP_ABS_REAL: { - } - case OP_NEG_REAL: { + DECODE_A(instruction) + i32 result; + u32 rd = fp + dest; + u32 r1 = fp + src1; + u32 r2 = fp + src2; + + i32 src1_val = (i32)mem[r1]; + i32 src2_val = (i32)mem[r2]; + + u32 src2_reciprocal = 1; + src2_reciprocal <<= 31; + src2_reciprocal = (u32)(src2_reciprocal / src2_val); + + result = src1_val * src2_reciprocal; + result <<= 1; + mem[rd] = result; + return true; } case OP_INT_TO_REAL: { + DECODE_A(instruction) + u32 rd = fp + dest; + u32 r1 = fp + src1; + USED(src2); + mem[rd] = (i32)mem[r1] << 16; + return true; } case OP_INT_TO_NAT: { + DECODE_A(instruction) + u32 rd = fp + dest; + u32 r1 = fp + src1; + USED(src2); + mem[rd] = (u32)mem[r1]; + return true; } case OP_NAT_TO_REAL: { + DECODE_A(instruction) + u32 rd = fp + dest; + u32 r1 = fp + src1; + USED(src2); + mem[rd] = (i32)mem[r1] << 16; + return true; } case OP_NAT_TO_INT: { + DECODE_A(instruction) + u32 rd = fp + dest; + u32 r1 = fp + src1; + USED(src2); + mem[rd] = (i32)mem[r1]; + return true; } case OP_REAL_TO_INT: { + DECODE_A(instruction) + u32 rd = fp + dest; + u32 r1 = fp + src1; + USED(src2); + mem[rd] = (i32)mem[r1] >> 16; + return true; } case OP_REAL_TO_NAT: { + DECODE_A(instruction) + u32 rd = fp + dest; + u32 r1 = fp + src1; + USED(src2); + mem[rd] = (u32)mem[r1] >> 16; + return true; } case OP_BIT_SHIFT_LEFT: { } @@ -136,6 +221,9 @@ bool step_vm() { case OP_BIT_XOR: { } case OP_JMP_IMM: { + DECODE_C(instruction) + pc = imm; + return true; } case OP_JMP_ABS: { } @@ -144,40 +232,58 @@ bool step_vm() { case OP_JMP_FLAG: { } case OP_JEQ_INT: { + COMPARE_AND_JUMP(i32, ==); } case OP_JNE_INT: { + COMPARE_AND_JUMP(i32, !=); } case OP_JGT_INT: { + COMPARE_AND_JUMP(i32, >); } case OP_JLT_INT: { + COMPARE_AND_JUMP(i32, <); } case OP_JLE_INT: { + COMPARE_AND_JUMP(i32, <=); } case OP_JGE_INT: { + COMPARE_AND_JUMP(i32, >=); } case OP_JEQ_NAT: { + COMPARE_AND_JUMP(u32, ==); } case OP_JNE_NAT: { + COMPARE_AND_JUMP(u32, !=); } case OP_JGT_NAT: { + COMPARE_AND_JUMP(u32, >); } case OP_JLT_NAT: { + COMPARE_AND_JUMP(u32, <); } case OP_JLE_NAT: { + COMPARE_AND_JUMP(u32, <=); } case OP_JGE_NAT: { + COMPARE_AND_JUMP(u32, >=); } case OP_JEQ_REAL: { + COMPARE_AND_JUMP(i32, ==); } case OP_JNE_REAL: { + COMPARE_AND_JUMP(i32, !=); } case OP_JGE_REAL: { + COMPARE_AND_JUMP(i32, >=); } case OP_JGT_REAL: { + COMPARE_AND_JUMP(i32, >); } case OP_JLT_REAL: { + COMPARE_AND_JUMP(i32, <); } case OP_JLE_REAL: { + COMPARE_AND_JUMP(i32, <=); } } diff --git a/vm/vm.h b/vm/vm.h index be3e180..96efd4a 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -35,7 +35,7 @@ u32 imm = ((u32)(instruction)) & 0xFFFFFF; typedef enum { - OP_HALT, /* halt : C : all zeros : halt execution */ + OP_HALT, /* halt : A : all zeros : halt execution */ OP_CALL, /* call : A : dest args fn_ptr : creates a new frame */ OP_RETURN, /* return : A : dest args : 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 */ @@ -69,20 +69,14 @@ typedef enum { 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_ABS_INT, /* abs_int : A : locals[dest] = | locals[src1] | */ - OP_NEG_INT, /* neg_int : A : locals[dest] = -locals[src1] */ 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_ABS_NAT, /* abs_nat : A : locals[dest] = | locals[src1] | */ - OP_NEG_NAT, /* neg_nat : A : locals[dest] = -locals[src1] */ 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_ABS_REAL, /* abs_real : A : locals[dest] = | locals[src1] | */ - OP_NEG_REAL, /* neg_real : A : locals[dest] = -locals[src1] */ 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 */ @@ -120,33 +114,33 @@ typedef enum { OP_MAX_OPCODE /* not an opcode count of instructions */ } Opcode; -#define MEM_SIZE 65536 +extern u32 pc; /* program counter */ +extern u32 cp; /* code pointer */ +extern u32 mp; /* memory pointer */ +extern u32 fp; /* frame pointer */ +extern u32 flag; /* flag */ +extern u8 interrupt; /* device interrupt */ +extern u32 *code; /* code */ +extern u8 *mem; /* memory */ -extern u32 mp; /* memory pointer */ -extern u32 cp; /* code pointer */ -extern u32 pc; /* program counter */ -extern u32 flag; /* flag */ -extern u32 *code; /* code */ -extern u8 *mem; /* memory */ +#define READ_U8(addr) (mem[addr]) -#define read_u8(addr) (mem[addr]) - -#define read_u16(addr) \ +#define READ_U16(addr) \ (((u16)mem[(addr) + 1] << 8) | ((u16)mem[(addr)])) -#define read_u32(addr) \ +#define READ_U32(addr) \ (((u32)mem[(addr) + 3] << 24) | \ ((u32)mem[(addr) + 2] << 16) | \ ((u32)mem[(addr) + 1] << 8) | ((u32)mem[(addr)])) -#define write_u8(addr, value) \ +#define WRITE_U8(addr, value) \ do { \ if ((addr) < sizeof(mem)) { \ mem[(addr)] = (value) & 0xFF; \ } \ } while (0) -#define write_u16(addr, value) \ +#define WRITE_U16(addr, value) \ do { \ if ((addr) + 1 < sizeof(mem)) { \ mem[(addr)] = (value) & 0xFF; \ @@ -154,7 +148,7 @@ extern u8 *mem; /* memory */ } \ } while (0) -#define write_u32(addr, value) \ +#define WRITE_U32(addr, value) \ do { \ if ((addr) + 3 < sizeof(mem)) { \ mem[(addr)] = (value) & 0xFF; \ @@ -164,7 +158,37 @@ extern u8 *mem; /* memory */ } \ } while (0) +#define MATH_OP(type, op) \ + do { \ + DECODE_A(instruction) \ + u32 rd = fp + dest; \ + u32 r1 = fp + src1; \ + u32 r2 = fp + src2; \ + mem[rd] = (type)mem[r1] op(type) mem[r2]; \ + return true; \ + } while (0) + +#define COMPARE_AND_JUMP(type, op) \ + do { \ + DECODE_A(instruction) \ + i32 cond; \ + u32 mask, target; \ + type value; \ + type value2; \ + u32 rd = fp + dest; \ + u32 r1 = fp + src1; \ + u32 r2 = fp + src2; \ + target = mem[rd]; \ + value = (type)mem[r1]; \ + value2 = (type)mem[r2]; \ + cond = !!(value op value2); \ + mask = -(u32)cond; \ + pc = (target & mask) | (pc & ~mask); \ + return true; \ + } while (0) + extern bool init_vm(); +extern u32 syscall(u32 id, u32 args, u32 mem_ptr); bool step_vm(); #endif