Refactor load/save to register/memory. Add memset variants

This commit is contained in:
zongor 2025-10-10 14:17:12 -07:00
parent 4d71d72e7a
commit 89574d9813
23 changed files with 464 additions and 319 deletions

View File

@ -56,8 +56,9 @@ endif
# --- EMSCRIPTEN-SPECIFIC ---
ifeq ($(PLATFORM), emscripten)
LDFLAGS += -s USE_SDL=2 -s WASM=1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s MAX_WEBGL_VERSION=2 \
--preload-file test/window.rom@paint.rom \
--preload-file test/paint-bw.rom@paint.rom \
-s INITIAL_MEMORY=16MB
# For release: optimize, strip debug, minimize size

View File

@ -9,10 +9,10 @@
#+PROPERTY: header-args :tangle-mode (identity #o0644)
#+BEGIN_SRC
[ᚢ · · ·
· ᚱ · ·
· · ᛋ ·
· · · ᚾ]
[ᚢ ᛫ ᛫ ᛫
᛫ ᚱ ᛫ ᛫
᛫ ᛫ ᛋ ᛫
᛫ ᛫ ᛫ ᚾ]
#+END_SRC
* Undâr
@ -88,7 +88,7 @@ heap allocations using the internal malloc opcode push pointers within this fram
(load-immediate $0 1)
(push $0)
(call &add) ; here a new frame is generated
(pop $0) ; the element is returned and the memory for the println is "freed" automatically because the child frame is done
(pop $0) ; the element is returned and the memory for the pln is "freed" automatically because the child frame is done
(halt))
(label add
@ -97,11 +97,11 @@ heap allocations using the internal malloc opcode push pointers within this fram
(add-int $2 $1 $0) ; add the arguments
(int-to-string $3 $2) ; convert to a string (heap allocation)
(push $3)
(call &println) ; call print function
(call &pln) ; call print function
(push $2)
(return)) ; return to main function
(label println
(label pln
(load-immediate $0 &terminal-namespace) ; load the namespace for the terminal
(load-immediate $3 &new-line) ; and a newline char
(pop $1) ; pointer to string

View File

@ -11,7 +11,7 @@
* Roadmap
** Memory System Improvements
in the beta phase the bump allocator will be removed and replaced with the following system: instead of the bump allocator memory and registers being separate, the frames are in vm memory and then dynamically allocate a frame and register with a size each time a function gets called of a particular arena size. the syntax would be fnN where N is the number is the size in kb for that particular frame, however the compiler will split up the available memory for that architecture into function arenas of the defined "theoretical maximum" of running coroutines. the "maximum" is going to be whatever is hardcoded for the VM, like 1MB or 100MB or 1GB or whatever. The true max will be <4GB because that is all that can be addressed by a u32. the sizes we can say that for a particular architecture has n many 128kb function and y many 8kb functions and so on; then the compiler could partition the system and report that the program requires x of this many slots of this size and y slots of another size. for strings we will extend the syntax we can use str8 is 8 bytes or str16 is 16 bytes or whatever, that way we have a shorthand that is consistent with the rest of the language and is friendly to new developers; however we would keep array syntax the same as in c-like languages `<type>[size]`. the stack and return stack need to be removed as well; like imagine you push some value onto the stack and then switch coroutines and then in that one it pops or pushes that would break. instead we will have a tiny stack per frame for function arguments and have a "return register" to allocate where the function should return to when it finishes. if it gets called recursively it will just take up a new block of the same size. recursive calls should be discouraged in general for this reason, its not a good technique for embedded development or permacomputing. so yes, it *will* compile, but guarantee the compiler *will* make fun of you. The compiler output in general should have an [[esolangs.org/wiki/INTERCAL][INTERCAL]] feel to it; the compiler needs to not take itself too seriously, but that does not mean it should not give useful advice to the programmer.
in the beta phase the bump allocator will be removed and replaced with the following system: instead of the bump allocator memory and registers being separate, the frames are in vm memory and then dynamically allocate a frame and register with a size each time a function gets called of a particular arena size. the syntax would be fnN where N is the number is the size in kb for that particular frame, however the compiler will split up the available memory for that architecture into function arenas of the defined "theoretical maximum" of running coroutines. the "maximum" is going to be whatever is hardcoded for the VM, like 1MB or 100MB or 1GB or whatever. The true max will be <4GB because that is all that can be addressed by a u32. the sizes we can say that for a particular architecture has n many 128kb function and y many 8kb functions and so on; then the compiler could partition the system and report that the program requires x of this many slots of this size and y slots of another size. for strings we will extend the syntax we can use str8 is 8 bytes or str16 is 16 bytes or whatever, that way we have a shorthand that is consistent with the rest of the language and is friendly to new developers; however we would keep array syntax the same as in c-like languages `<type>[size]`. the stack and return stack need to be removed as well; like imagine you push some value onto the stack and then switch coroutines and then in that one it pops or pushes that would break. instead we will have a tiny stack per frame for function arguments and have a "return register" to allocate where the function should return to when it finishes. if it gets called recursively it will just take up a new block of the same size. recursive calls should be discouraged in general for this reason, its not a good technique for embedded development or permacomputing. so yes, it *will* compile, but guarantee the compiler *will* make surreal comments about your code. The compiler output in general should have an [[esolangs.org/wiki/INTERCAL][INTERCAL]] feel to it; the compiler needs to not take itself too seriously, but that does not mean it should not give useful advice to the programmer.
** Coroutine System

View File

@ -1,6 +1,17 @@
function add(int a, int b) int {
Device term("/dev/term/0");
str new-line = "\n";
fn1 main() {
int sum = add(1, 1);
pln(sum.str);
}
fn1 add(int a, int b) int {
return a + b;
}
int sum = add(1, 1);
print(sum.str);
fn1 pln(str string) {
term.write(string);
term.write(new-line);
return;
}

View File

@ -1,6 +1,18 @@
function fib(int n) int {
Device term("/dev/term/0");
str new-line = "\n";
fn1 main() {
print(fib(35).str);
exit(0);
}
fn1 fib(int n) int {
if (n < 2) return n;
return fib(n - 2) + fib(n - 1);
}
print fib(35);
fn1 pln(str string) {
term.write(string);
term.write(new-line);
return;
}

View File

@ -1,3 +1,12 @@
function main(int argc, str[] argv) {
Device term("/dev/term/0");
str new-line = "\n";
fn1 main(int argc, str[] argv) {
print("nuqneH 'u'?");
}
fn1 pln(str string) {
term.write(string);
term.write(new-line);
return;
}

View File

@ -1,11 +1,21 @@
real a = 5.0;
do (int i = 5000, 0, -1) {
a = a + 5.0;
}
int b = a as nat;
print("Enter a string:");
str user_string = read();
print a.str;
print b.str;
print user_string;
Device term("/dev/term/0");
str new-line = "\n";
fn1 main() {
real a = 5.0;
do (int i = 5000, 0, -1) {
a = a + 5.0;
}
nat b = a as nat;
pln("Enter a string:");
str32 user_string = term.read();
pln(a.str);
pln(b.str);
pln(user_string);
}
fn1 pln(str string) {
term.write(string);
term.write(new-line);
return;
}

View File

@ -1,2 +1,13 @@
int sum = 1 + 2;
print(sum.str);
Device term("/dev/term/0");
str new-line = "\n";
fn1 main(int argc, str[] argv) {
int sum = 1 + 2;
pln(sum.str);
}
fn1 pln(str string) {
term.write(string);
term.write(new-line);
return;
}

View File

@ -76,7 +76,7 @@ i32 screen_write(void *data, const u8 *buffer, u32 size) {
if (!screen->surface && screen->window) {
const u8 *pixel_buffer = buffer;
int pitch = screen->width; // bytes per row
int pitch = screen->width; // bytes per row
screen->surface = SDL_CreateRGBSurfaceFrom((void *)pixel_buffer,
screen->width, screen->height,
@ -94,8 +94,8 @@ i32 screen_write(void *data, const u8 *buffer, u32 size) {
}
}
SDL_BlitScaled(screen->surface, NULL,
SDL_GetWindowSurface(screen->window), NULL);
SDL_BlitScaled(screen->surface, NULL, SDL_GetWindowSurface(screen->window),
NULL);
SDL_UpdateWindowSurface(screen->window);
return 0;
@ -150,52 +150,15 @@ i32 mouse_read(void *data, u8 *buffer, u32 size) {
return -1;
SDL_PumpEvents();
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
// Mouse events
case SDL_MOUSEMOTION:
mouse_data->x = event.motion.x;
mouse_data->y = event.motion.y;
break;
int x, y;
Uint32 state = SDL_GetMouseState(&x, &y);
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) mouse_data->btn1 = 1;
if (event.button.button == SDL_BUTTON_RIGHT) mouse_data->btn2 = 1;
if (event.button.button == SDL_BUTTON_MIDDLE) mouse_data->btn3 = 1;
if (event.button.button == SDL_BUTTON_X1) mouse_data->btn4 = 1;
break;
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT) mouse_data->btn1 = 0;
if (event.button.button == SDL_BUTTON_RIGHT) mouse_data->btn2 = 0;
if (event.button.button == SDL_BUTTON_MIDDLE) mouse_data->btn3 = 0;
if (event.button.button == SDL_BUTTON_X1) mouse_data->btn4 = 0;
break;
// Touch events (map to mouse_data as left-click equivalent)
case SDL_FINGERMOTION:
case SDL_FINGERDOWN:
case SDL_FINGERUP: {
float x = event.tfinger.x * 640;
float y = event.tfinger.y * 480;
mouse_data->x = (int)x;
mouse_data->y = (int)y;
// Only treat the first finger as mouse input (ignore multi-touch beyond 1 finger)
if (event.tfinger.fingerId == 0) {
if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) {
mouse_data->btn1 = 1;
} else if (event.type == SDL_FINGERUP) {
mouse_data->btn1 = 0;
}
}
break;
}
}
}
mouse_data->x = x;
mouse_data->y = y;
mouse_data->btn1 = (state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0;
mouse_data->btn2 = (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0;
mouse_data->btn3 = (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0;
mouse_data->btn4 = (state & SDL_BUTTON(SDL_BUTTON_X1)) ? 1 : 0;
u8 *info = (u8 *)buffer;
memcpy(&info[0], &mouse_data->x, sizeof(u32));

View File

@ -242,7 +242,7 @@ void repl(VM *vm) {
void register_sdl_devices(VM *vm) {
screen_data.width = 640;
screen_data.height = 480;
screen_data.size = 640 * 480;
screen_data.size = screen_data.width * screen_data.height;
vm_register_device(vm, "/dev/screen/0", "screen", &screen_data, &screen_ops);
@ -269,8 +269,8 @@ const char *opcode_to_string(Opcode op) {
[OP_CALL] = "call",
[OP_RETURN] = "return",
[OP_LOAD] = "load",
[OP_LOAD_REG] = "load-r",
[OP_LOAD_REG8] = "load-r8",
[OP_LOAD_REG] = "get",
[OP_LOAD_REG8] = "get-8",
[OP_LOADI8] = "load-i8",
[OP_LOADU8] = "load-u8",
[OP_LOADI16] = "load-i16",

View File

@ -80,16 +80,18 @@ int get_instruction_byte_size(ExprNode *node) {
return 2;
}
if (strcmp(opname, "int-to-string") == 0 ||
strcmp(opname, "nat-to-string") == 0 ||
strcmp(opname, "real-to-string") == 0 ||
strcmp(opname, "int-to-real") == 0 ||
strcmp(opname, "nat-to-real") == 0 ||
strcmp(opname, "real-to-int") == 0 || strcmp(opname, "load-r") == 0 ||
strcmp(opname, "real-to-nat") == 0 || strcmp(opname, "int-to-nat") == 0 ||
strcmp(opname, "nat-to-int") == 0 || strcmp(opname, "load-r8") == 0 ||
if (strcmp(opname, "int-to-string") == 0 || strcmp(opname, "get-8") == 0 ||
strcmp(opname, "nat-to-string") == 0 || strcmp(opname, "get-16") == 0 ||
strcmp(opname, "real-to-string") == 0 || strcmp(opname, "get") == 0 ||
strcmp(opname, "int-to-real") == 0 || strcmp(opname, "put-8") == 0 ||
strcmp(opname, "nat-to-real") == 0 || strcmp(opname, "put-16") == 0 ||
strcmp(opname, "real-to-int") == 0 || strcmp(opname, "put") == 0 ||
strcmp(opname, "real-to-nat") == 0 ||
strcmp(opname, "nat-to-int") == 0 || strcmp(opname, "int-to-nat") == 0 ||
strcmp(opname, "string-length") == 0 || strcmp(opname, "store") == 0 ||
strcmp(opname, "store-8") == 0 || strcmp(opname, "store-16") == 0 ||
strcmp(opname, "memset") == 0 || strcmp(opname, "memset") == 0 ||
strcmp(opname, "memset-8") == 0 || strcmp(opname, "memset-16") == 0 ||
strcmp(opname, "register-move") == 0 || strcmp(opname, "malloc") == 0) {
return 3;
}
@ -115,8 +117,7 @@ int get_instruction_byte_size(ExprNode *node) {
// Load, Load-immediate (6 bytes: 1 + 1 + 4)
if (strcmp(opname, "load") == 0 || strcmp(opname, "load-immediate") == 0 ||
strcmp(opname, "load-u16") == 0 || strcmp(opname, "load-i16") == 0 ||
strcmp(opname, "load-i8") == 0) {
strcmp(opname, "load-16") == 0 || strcmp(opname, "load-8") == 0) {
return 6;
}
@ -142,6 +143,7 @@ int get_instruction_byte_size(ExprNode *node) {
return 7;
}
// Syscall (1 + syscall_id (4) + args)
if (strcmp(opname, "syscall") == 0) {
return 1 + 4 + (node->child_count > 0 ? node->child_count - 1 : 0);
@ -438,68 +440,86 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
u32 addr = resolve_symbol(table, node->children[1]->token);
emit_byte(vm, reg);
emit_u32(vm, addr);
} else if (strcmp(opname, "load") == 0) {
emit_opcode(vm, OP_LOAD);
} else if (strcmp(opname, "load-8") == 0) {
emit_opcode(vm, OP_LOAD_8);
int dest = parse_register(node->children[0]->token);
u32 addr = resolve_symbol(table, node->children[1]->token);
emit_byte(vm, dest);
emit_u32(vm, addr);
} else if (strcmp(opname, "load-r") == 0) {
emit_opcode(vm, OP_LOAD_REG);
} else if (strcmp(opname, "load-16") == 0) {
emit_opcode(vm, OP_LOAD_8);
int dest = parse_register(node->children[0]->token);
u32 addr = resolve_symbol(table, node->children[1]->token);
emit_byte(vm, dest);
emit_u32(vm, addr);
} else if (strcmp(opname, "load") == 0) {
emit_opcode(vm, OP_LOAD_8);
int dest = parse_register(node->children[0]->token);
u32 addr = resolve_symbol(table, node->children[1]->token);
emit_byte(vm, dest);
emit_u32(vm, addr);
} else if (strcmp(opname, "get-8") == 0) {
emit_opcode(vm, OP_GET_8);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "load-r8") == 0) {
emit_opcode(vm, OP_LOAD_REG8);
} else if (strcmp(opname, "get-16") == 0) {
emit_opcode(vm, OP_GET_16);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
emit_byte(vm, src1);
} else if (strcmp(opname, "get") == 0) {
emit_opcode(vm, OP_GET_32);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "malloc") == 0) {
emit_opcode(vm, OP_MALLOC);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "load-i8") == 0) {
emit_opcode(vm, OP_LOADI8);
} else if (strcmp(opname, "memset-8") == 0) {
emit_opcode(vm, OP_MEMSET_8);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
int value = parse_register(node->children[1]->token);
int count = parse_register(node->children[2]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "load-u8") == 0) {
emit_opcode(vm, OP_LOADU8);
emit_byte(vm, value);
emit_byte(vm, count);
} else if (strcmp(opname, "memset-16") == 0) {
emit_opcode(vm, OP_MEMSET_16);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
int value = parse_register(node->children[1]->token);
int count = parse_register(node->children[2]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "load-u16") == 0) {
emit_opcode(vm, OP_LOADU16);
emit_byte(vm, value);
emit_byte(vm, count);
} else if (strcmp(opname, "memset") == 0) {
emit_opcode(vm, OP_MEMSET_32);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
int value = parse_register(node->children[1]->token);
int count = parse_register(node->children[2]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "load-i16") == 0) {
emit_opcode(vm, OP_LOADI16);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "store") == 0) {
emit_opcode(vm, OP_STORE);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
emit_byte(vm, value);
emit_byte(vm, count);
} else if (strcmp(opname, "store-8") == 0) {
emit_opcode(vm, OP_STORE8);
emit_opcode(vm, OP_STORE_8);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "store-16") == 0) {
emit_opcode(vm, OP_STORE16);
emit_opcode(vm, OP_STORE_16);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "store") == 0) {
emit_opcode(vm, OP_STORE_32);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
@ -560,7 +580,7 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
emit_byte(vm, dest);
emit_byte(vm, src1);
emit_byte(vm, src2);
} else if (strcmp(opname, "bit-shift-right-extend") == 0) {
} else if (strcmp(opname, "bit-shift-re") == 0) {
emit_opcode(vm, OP_SRE);
int dest = parse_register(node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
@ -711,7 +731,7 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
int dest = parse_register(node->children[0]->token);
int src = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src);
emit_byte(vm, src);
} else if (strcmp(opname, "jump-eq-int") == 0) {
emit_opcode(vm, OP_JEQ_INT);
u32 addr = resolve_symbol(table, node->children[0]->token);
@ -720,14 +740,14 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
emit_u32(vm, addr);
emit_byte(vm, src1);
emit_byte(vm, src2);
} else if (strcmp(opname, "jump-neq-int") == 0 ) {
} else if (strcmp(opname, "jump-neq-int") == 0) {
emit_opcode(vm, OP_JNEQ_INT);
u32 addr = resolve_symbol(table, node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
int src2 = parse_register(node->children[2]->token);
emit_u32(vm, addr);
emit_byte(vm, src1);
emit_byte(vm, src2);
emit_byte(vm, src2);
} else if (strcmp(opname, "jump-gt-int") == 0) {
emit_opcode(vm, OP_JGT_INT);
u32 addr = resolve_symbol(table, node->children[0]->token);
@ -768,14 +788,14 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
emit_u32(vm, addr);
emit_byte(vm, src1);
emit_byte(vm, src2);
} else if (strcmp(opname, "jump-neq-nat") == 0 ) {
} else if (strcmp(opname, "jump-neq-nat") == 0) {
emit_opcode(vm, OP_JNEQ_UINT);
u32 addr = resolve_symbol(table, node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
int src2 = parse_register(node->children[2]->token);
emit_u32(vm, addr);
emit_byte(vm, src1);
emit_byte(vm, src2);
emit_byte(vm, src2);
} else if (strcmp(opname, "jump-gt-nat") == 0) {
emit_opcode(vm, OP_JGT_UINT);
u32 addr = resolve_symbol(table, node->children[0]->token);
@ -816,14 +836,14 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
emit_u32(vm, addr);
emit_byte(vm, src1);
emit_byte(vm, src2);
} else if (strcmp(opname, "jump-neq-real") == 0 ) {
} else if (strcmp(opname, "jump-neq-real") == 0) {
emit_opcode(vm, OP_JNEQ_REAL);
u32 addr = resolve_symbol(table, node->children[0]->token);
int src1 = parse_register(node->children[1]->token);
int src2 = parse_register(node->children[2]->token);
emit_u32(vm, addr);
emit_byte(vm, src1);
emit_byte(vm, src2);
emit_byte(vm, src2);
} else if (strcmp(opname, "jump-gt-real") == 0) {
emit_opcode(vm, OP_JGT_REAL);
u32 addr = resolve_symbol(table, node->children[0]->token);

View File

@ -4,79 +4,84 @@
#include "common.h"
typedef enum {
OP_HALT, /* halt : terminate execution with code [src1] */
OP_JMP, /* jump : jump to address dest unconditionally */
OP_JMPF, /* jump-if-flag : jump to address dest if flag is ne 0 */
OP_CALL, /* call : creates a new frame */
OP_RETURN, /* return : returns from a frame to the parent frame */
OP_LOAD, /* load : dest = memory[src1 as u32] */
OP_LOAD_REG, /* load-r : dest = memory[registers[src1]] as u32 */
OP_LOAD_REG8, /* load-r8 : dest = memory[registers[src1]] as u8 */
OP_LOADI8, /* load-i8 : dest = memory[src1 as u32] */
OP_LOADU8, /* load-u8 : dest = memory[src1 as u32] */
OP_LOADI16, /* load-i16 : dest = memory[src1 as u32] */
OP_LOADU16, /* load-u16 : dest = memory[src1 as u32] */
OP_LOAD_IMM, /* load-immediate : dest = constant */
OP_MALLOC, /* malloc : dest = fat ptr to memory of ((src1 as size) + 4) */
OP_STORE, /* store : memory[dest] = src1 */
OP_STORE8, /* store-8 : memory[dest] = src1 << 8 */
OP_STORE16, /* store-16 : memory[dest] = src1 << 16 */
OP_PUSH, /* push : push const of ref */
OP_POP, /* pop : pop cosnt or ref */
OP_REG_MOV, /* register-move : dest = src1 */
OP_SYSCALL, /* syscall : src1 src2 src3 src4 more? does a system call based on args */
OP_SLL, /* bit-shift-left : dest = src1 << src2 */
OP_SRL, /* bit-shift-right : dest = src1 >> src2 */
OP_SRE, /* bit-shift-right-extend : dest as i32 = src1 >> src2 */
OP_BAND, /* bit-and : dest = src1 & src2 */
OP_BOR, /* bit-or : dest = src1 | src2 */
OP_BXOR, /* bit-xor : dest = src1 ^ src2 */
OP_ADD_INT, /* add-int : dest = src1 + src2 */
OP_SUB_INT, /* sub-int : dest = src1 - src2 */
OP_MUL_INT, /* mul-int : dest = src1 * src2 */
OP_DIV_INT, /* div-int : dest = src1 / src2 */
OP_ADD_UINT, /* add-nat : dest = src1 + src2 */
OP_SUB_UINT, /* sub-nat : dest = src1 - src2 */
OP_MUL_UINT, /* mul-nat : dest = src1 * src2 */
OP_DIV_UINT, /* div-nat : dest = src1 / src2 */
OP_ADD_REAL, /* add-real : dest = src1 + src2 */
OP_SUB_REAL, /* sub-real : dest = src1 - src2 */
OP_MUL_REAL, /* mul-real : dest = src1 * src2 */
OP_DIV_REAL, /* div-real : dest = src1 / src2 */
OP_INT_TO_REAL, /* int-to-real : dest = src1 as real */
OP_UINT_TO_REAL, /* nat-to-real : dest = src1 as real */
OP_REAL_TO_INT, /* real-to-int : dest = src1 as int */
OP_REAL_TO_UINT, /* real-to-nat : dest = src1 as uint */
OP_JEQ_INT, /* jump-eq-int : jump to address dest if src1 as int == src2 as int */
OP_JNEQ_INT, /* jump-neq-int : jump to address dest if src1 as int != src2 as int */
OP_JGT_INT, /* jump-gt-int : jump to address dest if src1 as int > src2 as int */
OP_JLT_INT, /* jump-lt-int : jump to address dest if src1 as int < src2 as int */
OP_JLE_INT, /* jump-le-int : jump to address dest if src1 as int <= src2 as int */
OP_JGE_INT, /* jump-ge-int : jump to address dest if src1 as int >= src2 as int */
OP_JEQ_UINT, /* jump-eq-nat : jump to address dest if src1 as uint == src2 as uint */
OP_JNEQ_UINT, /* jump-neq-nat : jump to address dest if src1 as uint != src2 as uint */
OP_JGT_UINT, /* jump-gt-nat : jump to address dest if src1 as uint > src2 as uint */
OP_JLT_UINT, /* jump-lt-nat : jump to address dest if src1 as uint < src2 as uint */
OP_JLE_UINT, /* jump-le-nat : jump to address dest if src1 as uint <= src2 as uint */
OP_JGE_UINT, /* jump-ge-nat : jump to address dest if src1 as uint >= src2 as uint */
OP_JEQ_REAL, /* jump-eq-real : jump to address dest if src1 as real == src2 as real */
OP_JNEQ_REAL, /* jump-neq-real : jump to address dest if src1 as real != src2 as real */
OP_JGE_REAL, /* jump-ge-real : jump to address dest if src1 as real >= src2 as real */
OP_JGT_REAL, /* jump-gt-real : jump to address dest if src1 as real > src2 as real */
OP_JLT_REAL, /* jump-lt-real : jump to address dest if src1 as real < src2 as real */
OP_JLE_REAL, /* jump-le-real : jump to address dest if src1 as real <= src2 as real */
OP_STRLEN, /* string-length : dest = length of str at src1 ptr */
OP_STREQ, /* string-eq : dest = src1 ptr string == src2 ptr string */
OP_STRCAT, /* string-concat : dest = ptr of src1 ptr string + src2 ptr string */
OP_STR_GET_CHAR, /* string-get-char : dest = ptr of src1 ptr str, src2 index of str */
OP_STR_FIND_CHAR, /* string-find-char : dest = ptr of src1 ptr string, src2 uint8 char */
OP_STR_SLICE, /* string-slice : dest = ptr of src1 ptr str, src2 start index, src3 end index */
OP_INT_TO_STRING, /* int-to-string : dest = src1 as str */
OP_UINT_TO_STRING, /* nat-to-string : dest = src1 as str */
OP_REAL_TO_STRING, /* real-to-string : dest = src1 as str */
OP_STRING_TO_INT, /* string-to-int : dest = src1 as int */
OP_STRING_TO_UINT, /* string-to-nat : dest = src1 as uint */
OP_STRING_TO_REAL /* string-to-real : dest = src1 as real */
OP_HALT, /* halt : terminate execution with code [src1] */
OP_JMP, /* jump : jump to address dest unconditionally */
OP_JMPF, /* jump-if-flag : jump to address dest if flag is ne 0 */
OP_CALL, /* call : creates a new frame */
OP_RETURN, /* return : returns from a frame to the parent frame */
OP_LOAD_IMM, /* load-immediate : dest = constant */
OP_GET_8, /* get-8 : dest = memory[registers[src1]] as u8 */
OP_GET_16, /* get-16 : dest = memory[registers[src1]] as u8 */
OP_GET_32, /* get : dest = memory[registers[src1]] as u32 */
OP_LOAD_8, /* load-8 : dest = memory[src1 as u32] */
OP_LOAD_16, /* load-16 : dest = memory[src1 as u32] */
OP_LOAD_32, /* load : dest = memory[src1 as u32] */
OP_STORE_8, /* store-8 : memory[dest] = src1 << 8 */
OP_STORE_16, /* store-16 : memory[dest] = src1 << 16 */
OP_STORE_32, /* store : memory[dest] = src1 */
OP_PUT_8, /* put-8 : memory[dest] = registers[src1] << 8 */
OP_PUT_16, /* put-16 : memory[dest] = registers[src1] << 16*/
OP_PUT_32, /* put : memory[dest] = registers[src1] */
OP_MALLOC, /* malloc : dest = fat ptr to memory of ((src1 as size) + 4) */
OP_MEMSET_8, /* memset-8 : dest <-> dest+count = src1 as u8 */
OP_MEMSET_16, /* memset-16 : dest <-> dest+count = src1 as u8 */
OP_MEMSET_32, /* memset-32 : dest <-> dest+count = src1 as u32 */
OP_PUSH, /* push : push const of ref */
OP_POP, /* pop : pop cosnt or ref */
OP_REG_MOV, /* register-move : dest = src1 */
OP_SYSCALL, /* syscall : src1 src2 src3 src4 more? does a system call based on args */
OP_SLL, /* bit-shift-left : dest = src1 << src2 */
OP_SRL, /* bit-shift-right : dest = src1 >> src2 */
OP_SRE, /* bit-shift-re : dest as i32 = src1 >> src2 */
OP_BAND, /* bit-and : dest = src1 & src2 */
OP_BOR, /* bit-or : dest = src1 | src2 */
OP_BXOR, /* bit-xor : dest = src1 ^ src2 */
OP_ADD_INT, /* add-int : dest = src1 + src2 */
OP_SUB_INT, /* sub-int : dest = src1 - src2 */
OP_MUL_INT, /* mul-int : dest = src1 * src2 */
OP_DIV_INT, /* div-int : dest = src1 / src2 */
OP_ADD_UINT, /* add-nat : dest = src1 + src2 */
OP_SUB_UINT, /* sub-nat : dest = src1 - src2 */
OP_MUL_UINT, /* mul-nat : dest = src1 * src2 */
OP_DIV_UINT, /* div-nat : dest = src1 / src2 */
OP_ADD_REAL, /* add-real : dest = src1 + src2 */
OP_SUB_REAL, /* sub-real : dest = src1 - src2 */
OP_MUL_REAL, /* mul-real : dest = src1 * src2 */
OP_DIV_REAL, /* div-real : dest = src1 / src2 */
OP_INT_TO_REAL, /* int-to-real : dest = src1 as real */
OP_UINT_TO_REAL, /* nat-to-real : dest = src1 as real */
OP_REAL_TO_INT, /* real-to-int : dest = src1 as int */
OP_REAL_TO_UINT, /* real-to-nat : dest = src1 as uint */
OP_JEQ_INT, /* jump-eq-int : jump to address dest if src1 as int == src2 as int */
OP_JNEQ_INT, /* jump-neq-int : jump to address dest if src1 as int != src2 as int */
OP_JGT_INT, /* jump-gt-int : jump to address dest if src1 as int > src2 as int */
OP_JLT_INT, /* jump-lt-int : jump to address dest if src1 as int < src2 as int */
OP_JLE_INT, /* jump-le-int : jump to address dest if src1 as int <= src2 as int */
OP_JGE_INT, /* jump-ge-int : jump to address dest if src1 as int >= src2 as int */
OP_JEQ_UINT, /* jump-eq-nat : jump to address dest if src1 as uint == src2 as uint */
OP_JNEQ_UINT, /* jump-neq-nat : jump to address dest if src1 as uint != src2 as uint */
OP_JGT_UINT, /* jump-gt-nat : jump to address dest if src1 as uint > src2 as uint */
OP_JLT_UINT, /* jump-lt-nat : jump to address dest if src1 as uint < src2 as uint */
OP_JLE_UINT, /* jump-le-nat : jump to address dest if src1 as uint <= src2 as uint */
OP_JGE_UINT, /* jump-ge-nat : jump to address dest if src1 as uint >= src2 as uint */
OP_JEQ_REAL, /* jump-eq-real : jump to address dest if src1 as real == src2 as real */
OP_JNEQ_REAL, /* jump-neq-real : jump to address dest if src1 as real != src2 as real */
OP_JGE_REAL, /* jump-ge-real : jump to address dest if src1 as real >= src2 as real */
OP_JGT_REAL, /* jump-gt-real : jump to address dest if src1 as real > src2 as real */
OP_JLT_REAL, /* jump-lt-real : jump to address dest if src1 as real < src2 as real */
OP_JLE_REAL, /* jump-le-real : jump to address dest if src1 as real <= src2 as real */
OP_STRLEN, /* string-length : dest = length of str at src1 ptr */
OP_STREQ, /* string-eq : dest = src1 ptr string == src2 ptr string */
OP_STRCAT, /* string-concat : dest = ptr of src1 ptr string + src2 ptr string */
OP_STR_GET_CHAR, /* string-get-char : dest = ptr of src1 ptr str, src2 index of str */
OP_STR_FIND_CHAR, /* string-find-char : dest = ptr of src1 ptr string, src2 uint8 char */
OP_STR_SLICE, /* string-slice : dest = ptr of src1 ptr str, src2 start index, src3 end index */
OP_INT_TO_STRING, /* int-to-string : dest = src1 as str */
OP_UINT_TO_STRING, /* nat-to-string : dest = src1 as str */
OP_REAL_TO_STRING, /* real-to-string : dest = src1 as str */
OP_STRING_TO_INT, /* string-to-int : dest = src1 as int */
OP_STRING_TO_UINT, /* string-to-nat : dest = src1 as uint */
OP_STRING_TO_REAL /* string-to-real : dest = src1 as real */
} Opcode;
#define MAX_REGS 32
@ -101,7 +106,8 @@ typedef struct device_ops_s {
i32 (*read)(void *device_data, u8 *buffer, u32 size);
i32 (*write)(void *device_data, const u8 *buffer, u32 size);
i32 (*close)(void *device_data);
i32 (*ioctl)(void *device_data, u32 cmd, const u8 *buffer); /* optional control */
i32 (*ioctl)(void *device_data, u32 cmd,
const u8 *buffer); /* optional control */
} DeviceOps;
#define DEVICE_TYPE_MAX_LENGTH 24 /* 23 chars + null terminator */

View File

@ -109,6 +109,102 @@ bool step_vm(VM *vm) {
vm->mp += (size + 4);
return true;
}
case OP_MEMSET_32: {
u32 i, start, end;
u8 dest_reg = read_u8(vm, code, vm->pc++);
u8 value_reg = read_u8(vm, code, vm->pc++);
u8 count_reg = read_u8(vm, code, vm->pc++);
u32 dest = frame->registers[dest_reg];
u32 value = frame->registers[value_reg];
u32 count = frame->registers[count_reg];
if (count == 0) {
vm->flag = 1;
return true;
}
start = dest;
end = dest + count;
if (start >= vm->mp || count > vm->mp ||
end > vm->mp) {
vm->flag = 0;
return true;
}
for (i = start; i < end; i+=4) {
write_u32(vm, memory, i, value);
}
frame->registers[0] = dest;
vm->flag = 1;
return true;
}
case OP_MEMSET_16: {
u32 i, start, end;
u8 dest_reg = read_u8(vm, code, vm->pc++);
u8 value_reg = read_u8(vm, code, vm->pc++);
u8 count_reg = read_u8(vm, code, vm->pc++);
u32 dest = frame->registers[dest_reg];
u16 value = (u16)(frame->registers[value_reg]);
u32 count = frame->registers[count_reg];
if (count == 0) {
vm->flag = 1;
return true;
}
start = dest;
end = dest + count;
if (start >= vm->mp || count > vm->mp ||
end > vm->mp) {
vm->flag = 0;
return true;
}
for (i = start; i < end; i+=2) {
write_u16(vm, memory, i, value);
}
frame->registers[0] = dest;
vm->flag = 1;
return true;
}
case OP_MEMSET_8: {
u32 i, start, end;
u8 dest_reg = read_u8(vm, code, vm->pc++);
u8 value_reg = read_u8(vm, code, vm->pc++);
u8 count_reg = read_u8(vm, code, vm->pc++);
u32 dest = frame->registers[dest_reg];
u8 value = (u8)(frame->registers[value_reg]);
u32 count = frame->registers[count_reg];
if (count == 0) {
vm->flag = 1;
return true;
}
start = dest;
end = dest + count;
if (start >= vm->mp || count > vm->mp ||
end > vm->mp) {
vm->flag = 0;
return true;
}
for (i = start; i < end; i++) {
write_u8(vm, memory, i, value);
}
frame->registers[0] = dest;
vm->flag = 1;
return true;
}
case OP_LOAD_IMM: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
@ -117,7 +213,7 @@ bool step_vm(VM *vm) {
frame->registers[dest] = v;
return true;
}
case OP_LOAD: {
case OP_LOAD_32: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = read_u32(vm, code, vm->pc);
@ -126,7 +222,25 @@ bool step_vm(VM *vm) {
frame->registers[dest] = v;
return true;
}
case OP_LOAD_REG: {
case OP_LOAD_16: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = read_u32(vm, code, vm->pc);
vm->pc += 4;
v = read_u16(vm, memory, ptr);
frame->registers[dest] = v;
return true;
}
case OP_LOAD_8: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = read_u32(vm, code, vm->pc);
vm->pc += 4;
v = read_u8(vm, memory, ptr);
frame->registers[dest] = v;
return true;
}
case OP_GET_32: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
@ -136,7 +250,18 @@ bool step_vm(VM *vm) {
frame->registers[dest] = ptr;
return true;
}
case OP_LOAD_REG8: {
case OP_GET_16: {
u16 v16;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
v = frame->registers[src1];
v16 = read_u16(vm, memory, v);
frame->registers[dest] = v16;
return true;
}
case OP_GET_8: {
u8 v8;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
@ -147,47 +272,7 @@ bool step_vm(VM *vm) {
frame->registers[dest] = v8;
return true;
}
case OP_LOADI8: {
i8 v8;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = read_u32(vm, code, vm->pc);
vm->pc += 4;
v8 = (i8)read_u8(vm, memory, ptr);
frame->registers[ptr] = v8;
return true;
}
case OP_LOADU8: {
u8 v8;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = read_u32(vm, code, vm->pc);
vm->pc += 4;
v8 = read_u8(vm, memory, ptr);
frame->registers[ptr] = v8;
return true;
}
case OP_LOADI16: {
i16 v16;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = read_u32(vm, code, vm->pc);
vm->pc += 4;
v16 = (i16)read_u16(vm, memory, ptr);
frame->registers[dest] = v16;
return true;
}
case OP_LOADU16: {
u16 v16;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = read_u32(vm, code, vm->pc);
vm->pc += 4;
v16 = read_u16(vm, memory, ptr);
frame->registers[ptr] = v16;
return true;
}
case OP_STORE: {
case OP_STORE_32: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
@ -197,7 +282,17 @@ bool step_vm(VM *vm) {
write_u32(vm, memory, ptr, v);
return true;
}
case OP_STORE8: {
case OP_STORE_16: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
v = frame->registers[src1];
ptr = frame->registers[dest];
write_u16(vm, memory, ptr, v);
return true;
}
case OP_STORE_8: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
@ -207,14 +302,36 @@ bool step_vm(VM *vm) {
write_u8(vm, memory, ptr, v);
return true;
}
case OP_STORE16: {
case OP_PUT_32: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
v = frame->registers[src1];
ptr = frame->registers[dest];
write_u16(vm, memory, ptr, v);
v = frame->registers[src1];
write_u32(vm, memory, ptr, v);
return true;
}
case OP_PUT_16: {
u16 v16;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = frame->registers[dest];
v16 = frame->registers[src1];
write_u16(vm, memory, ptr, v16);
return true;
}
case OP_PUT_8: {
u8 v8;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
ptr = frame->registers[dest];
v8 = frame->registers[src1];
write_u8(vm, memory, ptr, v8);
return true;
}
case OP_PUSH: {
@ -302,8 +419,7 @@ bool step_vm(VM *vm) {
dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
if (dev && dev->ops->read) {
vm->flag =
dev->ops->read(dev->data, &vm->memory[buffer_ptr + 4], size);
vm->flag = dev->ops->read(dev->data, &vm->memory[buffer_ptr + 4], size);
frame->registers[buffer_reg] = buffer_ptr;
} else {
vm->flag = 0;

View File

@ -1,32 +1,24 @@
((code
(label main
(load-immediate $0 1)
(push $0)
(load-immediate $0 1)
(push $0)
(call &add)
(pop $0)
(int-to-string $1 $0)
(push $1)
(call &println)
(halt))
(label add
(pop $0)
(pop $1)
(add-int $2 $1 $0)
(push $2)
(return))
(module add
(const terminal-namespace "/dev/term/0")
(const new-line "\n")
(label println
(fn :1 main ()
(load-immediate $0 1)
(load-immediate $1 1)
(call &add ($0 $1) $2)
(int-to-string $1 $2)
(call &pln ($1))
(halt))
(fn :1 add ($0 $1)
(add-int $2 $1 $0)
(return $2))
(fn :1 pln ($1)
(load-immediate $0 &terminal-namespace)
(load-immediate $3 &new-line)
(pop $1)
(string-length $2 $1)
(syscall WRITE $0 $1 $2)
(string-length $4 $3)
(syscall WRITE $0 $3 $4)
(return)))
(data
(label terminal-namespace "/dev/term/0")
(label new-line "\n")))

View File

@ -6,7 +6,7 @@
(pop $0)
(int-to-string $1 $0)
(push $1)
(call &println)
(call &pln)
(halt))
(label fib
(pop $0)
@ -28,7 +28,7 @@
(label base-case
(push $0)
(return)))
(label println
(label pln
(load-immediate $0 &terminal-namespace)
(load-immediate $3 &new-line)
(pop $1)

View File

@ -19,15 +19,15 @@
(malloc $11 $8)
(syscall READ $10 $2 $8 $11)
(push $2)
(call &println)
(call &pln)
(nat-to-string $4 $1)
(push $4)
(call &println)
(call &pln)
(real-to-string $3 $0)
(push $3)
(call &println)
(call &pln)
(halt))
(label println
(label pln
(load-immediate $0 &terminal-namespace)
(load-immediate $3 &new-line)
(pop $1)

View File

@ -3,14 +3,14 @@
(load-immediate $0 &terminal-namespace) ; get terminal device
(load-immediate $1 &help) ; print help message
(push $1)
(call &println)
(call &pln)
(load-immediate $1 32) ; read in a string of max 32 char length
(malloc $2 $1) ; allocate memory for the string
(syscall READ $0 $3 $1 $2) ; read the string
(push $3)
(call &println) ; print the string
(call &pln) ; print the string
(halt))
(label println
(label pln
(load-immediate $0 &terminal-namespace)
(load-immediate $3 &new-line)
(pop $1)

View File

@ -15,11 +15,11 @@
(load-immediate $1 12) ; offset for width
(add-nat $19 $18 $1)
(load-r $20 $19) ; load width
(get $20 $19) ; load width
(load-immediate $1 8) ; offset for size
(add-nat $19 $18 $1)
(load-r $22 $19) ; load size
(get $22 $19) ; load size
(malloc $21 $22) ; malloc frame buffer
@ -29,25 +29,27 @@
(load-immediate $14 20) ; box size
(syscall WRITE $0 $21 $22)
(label draw-loop
; load mouse click data
(syscall READ $16 $2 $3 $4)
(syscall READ $16 $2 $3 $4)
(load-immediate $5 4) ; offset for x
(add-nat $6 $5 $2)
(load-r $7 $6) ; load x
(get $7 $6) ; load x
(load-immediate $5 8) ; offset for y
(add-nat $6 $5 $2)
(load-r $8 $6) ; load y
(get $8 $6) ; load y
(load-immediate $5 12) ; offset for btn1
(add-nat $6 $5 $2)
(load-r8 $9 $6) ; load btn1 pressed
(get-8 $9 $6) ; load btn1 pressed
(load-immediate $5 13) ; offset for btn2
(add-nat $6 $5 $2)
(load-r8 $10 $6) ; load btn2 pressed
(get-8 $10 $6) ; load btn2 pressed
; first row
(push $21)
@ -207,10 +209,7 @@
(add-int $6 $4 $12) ; $6 = row end = current + width
(register-move $7 $4) ; $7 = pixel pointer
(label draw-box-inner
(store-8 $7 $3) ; write color
(add-int $7 $7 $1) ; next pixel
(jump-lt-int &draw-box-inner $7 $6))
(memset-8 $7 $3 $12)
(add-int $4 $4 $2) ; next row (+= 640)
(sub-int $5 $5 $1) ; decrement row count

Binary file not shown.

View File

@ -12,10 +12,10 @@
(syscall IOCTL $0 $16 $18)
(load-immediate $1 12) ; offset for width
(add-nat $19 $18 $1)
(load-r $20 $19) ; load width
(get $20 $19) ; load width
(load-immediate $1 8) ; offset for size
(add-nat $19 $18 $1)
(load-r $22 $19) ; load size
(get $22 $19) ; load size
(malloc $21 $22) ; malloc frame buffer
(syscall WRITE $0 $21 $22)
@ -28,16 +28,16 @@
(syscall READ $16 $2 $3 $4)
(load-immediate $5 4) ; offset for x
(add-nat $6 $5 $2)
(load-r $7 $6) ; load x
(get $7 $6) ; load x
(load-immediate $5 8) ; offset for y
(add-nat $6 $5 $2)
(load-r $8 $6) ; load y
(get $8 $6) ; load y
(load-immediate $5 12) ; offset for btn1
(add-nat $6 $5 $2)
(load-r8 $9 $6) ; load btn1 pressed
(get-8 $9 $6) ; load btn1 pressed
(load-immediate $5 13) ; offset for btn2
(add-nat $6 $5 $2)
(load-r8 $10 $6) ; load btn2 pressed
(get-8 $10 $6) ; load btn2 pressed
(load-immediate $14 20) ; box size
@ -371,12 +371,7 @@
(label draw-box-outer
(add-int $6 $4 $12) ; $6 = row end = current + width
(register-move $7 $4) ; $7 = pixel pointer
(label draw-box-inner
(store-8 $7 $3) ; write color
(add-int $7 $7 $1) ; next pixel
(jump-lt-int &draw-box-inner $7 $6))
(memset-8 $7 $3 $12) ; draw row
(add-int $4 $4 $2) ; next row (+= 640)
(sub-int $5 $5 $1) ; decrement row count
(jump-gt-int &draw-box-outer $5 0))

Binary file not shown.

View File

@ -5,9 +5,9 @@
(add-real $2 $1 $0)
(real-to-string $3 $2)
(push $3)
(call &println)
(call &pln)
(halt))
(label println
(label pln
(load-immediate $0 &terminal-namespace)
(load-immediate $3 &new-line)
(pop $1)

View File

@ -10,10 +10,10 @@
(syscall IOCTL $0 $16 $18)
(load-immediate $1 12) ; offset for width
(add-nat $19 $18 $1)
(load-r $20 $19) ; load width
(get $20 $19) ; load width
(load-immediate $1 8) ; offset for size
(add-nat $19 $18 $1)
(load-r $22 $19) ; load size
(get $22 $19) ; load size
(malloc $21 $22) ; malloc frame buffer
(syscall WRITE $0 $21 $22)
@ -23,23 +23,23 @@
(nat-to-string $5 $4)
(push $5)
(call &println)
(call &pln)
(label draw-loop
; load mouse click data
(syscall READ $16 $2 $3 $4)
(load-immediate $5 12) ; offset for btn1
(add-nat $6 $5 $2)
(load-r8 $9 $6) ; load btn1 pressed
(get-8 $9 $6) ; load btn1 pressed
(jump-eq-nat &draw-loop $9 $11)
(load-immediate $5 4) ; offset for x
(add-nat $6 $5 $2)
(load-r $7 $6) ; load x
(get $7 $6) ; load x
(load-immediate $5 8) ; offset for y
(add-nat $6 $5 $2)
(load-r $8 $6) ; load y
(get $8 $6) ; load y
; Compute start address: y*width + x
(mul-nat $15 $8 $20) ; $15 = y * width
@ -54,11 +54,11 @@
(load-immediate $5 13) ; offset for btn2
(add-nat $6 $5 $2)
(load-r8 $10 $6) ; load btn2 pressed
(get-8 $10 $6) ; load btn2 pressed
(jump-eq-nat &draw-loop $10 $11))
(halt))
(label println
(label pln
(load-immediate $0 &terminal-namespace)
(load-immediate $3 &new-line)
(pop $1)