add and fibbonacci examples now working

This commit is contained in:
zongor 2025-09-23 22:08:28 -07:00
parent 77745c8880
commit f650e8110b
7 changed files with 177 additions and 61 deletions

View File

@ -11,16 +11,24 @@ i32 console_open(void *data, u32 mode) {
i32 console_read(void *data, u8 *buffer, u32 size) { i32 console_read(void *data, u8 *buffer, u32 size) {
USED(data); USED(data);
ssize_t result = read(STDIN_FILENO, buffer, size); for (u32 i = 0; i < size; i++) {
if (result < 0) return -1; /* Error */ u8 ch = getchar();
return (i32)result; /* Bytes read */ if (ch == '\0')
break;
if (ch == '\n')
break;
buffer[i] = ch;
}
return 0;
} }
i32 console_write(void *data, const u8 *buffer, u32 size) { i32 console_write(void *data, const u8 *buffer, u32 size) {
USED(data); USED(data);
ssize_t result = write(STDOUT_FILENO, buffer, size); for (u32 i = 0; i < size; i++) {
if (result < 0) return -1; /* Error */ putchar(buffer[i]);
return (i32)result; /* Bytes written */ }
return 0;
} }
i32 console_close(void *data) { i32 console_close(void *data) {

View File

@ -227,6 +227,73 @@ void register_sdl_devices(VM *vm) {
&keyboard_ops); &keyboard_ops);
} }
const char* opcode_to_string(Opcode op) {
static const char* names[] = {
[OP_HALT] = "halt",
[OP_JMP] = "jump",
[OP_JMPF] = "jump-if-flag",
[OP_CALL] = "call",
[OP_RETURN] = "return",
[OP_LOAD] = "load",
[OP_LOAD_IMM] = "load-immediate",
[OP_STORE] = "store",
[OP_PUSH] = "push",
[OP_POP] = "pop",
[OP_REG_MOV] = "register-move",
[OP_SYSCALL] = "syscall",
[OP_ADD_INT] = "add-int",
[OP_SUB_INT] = "sub-int",
[OP_MUL_INT] = "mul-int",
[OP_DIV_INT] = "div-int",
[OP_ADD_UINT] = "add-nat",
[OP_SUB_UINT] = "sub-nat",
[OP_MUL_UINT] = "mul-nat",
[OP_DIV_UINT] = "div-nat",
[OP_ADD_REAL] = "add-real",
[OP_SUB_REAL] = "sub-real",
[OP_MUL_REAL] = "mul-real",
[OP_DIV_REAL] = "div-real",
[OP_INT_TO_REAL] = "int-to-real",
[OP_UINT_TO_REAL] = "nat-to-real",
[OP_REAL_TO_INT] = "real-to-int",
[OP_REAL_TO_UINT] = "real-to-nat",
[OP_JEQ_INT] = "jump-eq-int",
[OP_JGT_INT] = "jump-gt-int",
[OP_JLT_INT] = "jump-lt-int",
[OP_JLE_INT] = "jump-le-int",
[OP_JGE_INT] = "jump-ge-int",
[OP_JEQ_UINT] = "jump-eq-nat",
[OP_JGT_UINT] = "jump-gt-nat",
[OP_JLT_UINT] = "jump-lt-nat",
[OP_JLE_UINT] = "jump-le-nat",
[OP_JGE_UINT] = "jump-ge-nat",
[OP_JEQ_REAL] = "jump-eq-real",
[OP_JGE_REAL] = "jump-ge-real",
[OP_JGT_REAL] = "jump-gt-real",
[OP_JLT_REAL] = "jump-lt-real",
[OP_JLE_REAL] = "jump-le-real",
[OP_STRLEN] = "string-length",
[OP_STREQ] = "string-eq",
[OP_STRCAT] = "string-concat",
[OP_STR_GET_CHAR] = "string-get-char",
[OP_STR_FIND_CHAR]= "string-find-char",
[OP_STR_SLICE] = "string-slice",
[OP_INT_TO_STRING] = "int-to-string",
[OP_UINT_TO_STRING] = "nat-to-string",
[OP_REAL_TO_STRING] = "real-to-string",
[OP_STRING_TO_INT] = "string-to-int",
[OP_STRING_TO_UINT] = "string-to-nat",
[OP_STRING_TO_REAL] = "string-to-real"
};
if (op < 0 || op >= (int)(sizeof(names) / sizeof(names[0]))) {
return "<invalid-opcode>";
}
const char* name = names[op];
return name ? name : "<unknown-opcode>";
}
i32 main(i32 argc, char *argv[]) { i32 main(i32 argc, char *argv[]) {
struct CompilerConfig config = {0}; struct CompilerConfig config = {0};
@ -352,6 +419,7 @@ i32 main(i32 argc, char *argv[]) {
} }
} else { } else {
while (running) { while (running) {
//printf("| %d %s %d\n", vm.code[vm.pc], opcode_to_string(vm.code[vm.pc]), vm.pc);
running = step_vm(&vm); running = step_vm(&vm);
} }
} }

View File

@ -58,7 +58,6 @@ Symbol *symbol_table_lookup(SymbolTable *table, const char *name) {
return NULL; return NULL;
} }
// Add this helper for your current code
u32 find_label_in_table(SymbolTable *table, const char *name) { u32 find_label_in_table(SymbolTable *table, const char *name) {
Symbol *sym = symbol_table_lookup(table, name); Symbol *sym = symbol_table_lookup(table, name);
if (!sym) { if (!sym) {
@ -77,39 +76,71 @@ int get_instruction_byte_size(ExprNode *node) {
} }
// Register-based opcodes (2 bytes: opcode + register) // Register-based opcodes (2 bytes: opcode + register)
if (strcmp(opname, "pop") == 0 || strcmp(opname, "push") == 0) { if (strcmp(opname, "pop") == 0 || strcmp(opname, "push") == 0 ||
strcmp(opname, "jump") == 0 || strcmp(opname, "jump-if-flag") == 0) {
return 2; return 2;
} }
if (strcmp(opname, "int-to-string") == 0 || 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, "real-to-nat") == 0 || strcmp(opname, "int-to-nat") == 0 ||
strcmp(opname, "nat-to-int") == 0 ||
strcmp(opname, "string-length") == 0) { strcmp(opname, "string-length") == 0) {
return 3; return 3;
} }
// Load/store with register and address (5 bytes: 1 + 1 + 4) // Load/store with register and address (5 bytes: 1 + 1 + 4)
if (strcmp(opname, "load") == 0 || strcmp(opname, "store") == 0 || if (strcmp(opname, "load") == 0 || strcmp(opname, "store") == 0 ||
strcmp(opname, "jump") == 0 || strcmp(opname, "jump-if-flag") == 0 ||
strcmp(opname, "call") == 0) { strcmp(opname, "call") == 0) {
return 5; return 5;
} }
// Register-register-register opcodes (4 bytes: 1 + 3) // Register-register-register opcodes (4 bytes: 1 + 3)
if (strcmp(opname, "add-int") == 0 || strcmp(opname, "sub-int") == 0) { if (strcmp(opname, "add-int") == 0 || strcmp(opname, "sub-int") == 0 ||
strcmp(opname, "mul-int") == 0 || strcmp(opname, "div-int") == 0 ||
strcmp(opname, "add-nat") == 0 || strcmp(opname, "sub-nat") == 0 ||
strcmp(opname, "mul-nat") == 0 || strcmp(opname, "div-nat") == 0 ||
strcmp(opname, "add-real") == 0 || strcmp(opname, "sub-real") == 0 ||
strcmp(opname, "mul-real") == 0 || strcmp(opname, "div-real") == 0) {
return 4; return 4;
} }
// Load-immediate (5 bytes: 1 + 1 + 4) // Load, Load-immediate (5 bytes: 1 + 1 + 4)
if (strcmp(opname, "load-immediate") == 0) { if (strcmp(opname, "load-immediate") == 0 || strcmp(opname, "load") == 0 ||
strcmp(opname, "store") == 0) {
return 6; return 6;
} }
// jump compare (7 bytes: 1 + 4 + 1 + 1)
if (strcmp(opname, "jump-eq-int") == 0 ||
strcmp(opname, "jump-gt-int") == 0 ||
strcmp(opname, "jump-lt-int") == 0 ||
strcmp(opname, "jump-le-int") == 0 ||
strcmp(opname, "jump-ge-int") == 0 ||
strcmp(opname, "jump-eq-nat") == 0 ||
strcmp(opname, "jump-gt-nat") == 0 ||
strcmp(opname, "jump-lt-nat") == 0 ||
strcmp(opname, "jump-le-nat") == 0 ||
strcmp(opname, "jump-ge-nat") == 0 ||
strcmp(opname, "jump-eq-real") == 0 ||
strcmp(opname, "jump-gt-real") == 0 ||
strcmp(opname, "jump-lt-real") == 0 ||
strcmp(opname, "jump-le-real") == 0 ||
strcmp(opname, "jump-ge-real") == 0) {
return 7;
}
// Syscall (1 + syscall_id (4) + args) // Syscall (1 + syscall_id (4) + args)
if (strcmp(opname, "syscall") == 0) { if (strcmp(opname, "syscall") == 0) {
return 1 + 4 + (node->child_count > 0 ? node->child_count - 1 : 0); return 1 + 4 + (node->child_count > 0 ? node->child_count - 1 : 0);
} }
fprintf(stderr, "Unknown opcode for sizing: %s\n", opname); fprintf(stderr, "Unknown opcode for sizing: %s\n", opname);
return 4; // Conservative fallback exit(-1);
} }
int calculate_instruction_size(ExprNode *node) { int calculate_instruction_size(ExprNode *node) {
@ -125,12 +156,12 @@ void collect_symbols_in_node(SymbolTable *table, ExprNode *node,
for (int i = 0; i < depth; i++) for (int i = 0; i < depth; i++)
strcat(indent, " "); strcat(indent, " ");
printf("%sProcessing: %s (addr=%d)\n", indent, node->token, *current_addr); //printf("%s%d %s ", indent, *current_addr, node->token);
if (strcmp(node->token, "label") == 0) { if (strcmp(node->token, "label") == 0) {
if (node->child_count >= 1) { if (node->child_count >= 1) {
const char *name = node->children[0]->token; const char *name = node->children[0]->token;
printf("%s ADDING LABEL: %s -> %d\n", indent, name, *current_addr); //printf(" %s -> %d\n", name, *current_addr);
symbol_table_add(table, name, *current_addr, SYMBOL_CODE); symbol_table_add(table, name, *current_addr, SYMBOL_CODE);
} }
@ -141,7 +172,8 @@ void collect_symbols_in_node(SymbolTable *table, ExprNode *node,
} else { } else {
int size = get_instruction_byte_size(node); int size = get_instruction_byte_size(node);
*current_addr += size; *current_addr += size;
printf("%s +%d bytes -> %d\n", indent, size, *current_addr); //printf(" +%d bytes -> %d\n", size, *current_addr);
//printf("\n");
} }
} }

View File

@ -98,8 +98,8 @@ typedef struct device_s {
u32 flags; /* permissions, status, etc. */ u32 flags; /* permissions, status, etc. */
} Device; } Device;
#define MEMORY_SIZE 1024 /*(640 * 480 + 65536)*/ #define MEMORY_SIZE (640 * 480 + 65536)
#define CODE_SIZE 128 /*8192*/ #define CODE_SIZE 8192
#define FRAMES_SIZE 128 #define FRAMES_SIZE 128
#define STACK_SIZE 256 #define STACK_SIZE 256
#define DEVICES_SIZE 8 #define DEVICES_SIZE 8
@ -111,7 +111,7 @@ typedef struct vm_s {
u32 rp; /* return stack pointer (top of stack) */ u32 rp; /* return stack pointer (top of stack) */
u32 mp; /* memory pointer (last allocated value) */ u32 mp; /* memory pointer (last allocated value) */
u32 dc; /* device count */ u32 dc; /* device count */
u32 flag; /* flag (temporary results like SYSCALL status) */ i32 flag; /* flag (temporary results like SYSCALL status) */
Frame frames[FRAMES_SIZE]; /* function call frames */ Frame frames[FRAMES_SIZE]; /* function call frames */
u32 stack[STACK_SIZE]; /* main stack */ u32 stack[STACK_SIZE]; /* main stack */
u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */ u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */

View File

@ -7,20 +7,19 @@
do { \ do { \
i32 cond; \ i32 cond; \
u32 mask, target; \ u32 mask, target; \
u8 dest, src1, src2; \ u8 src1, src2; \
type value; \ type value; \
type value2; \ type value2; \
dest = read_u8(vm, code, vm->pc); \ target = read_u32(vm, code, vm->pc); \
vm->pc++; \ vm->pc+=4; \
src1 = read_u8(vm, code, vm->pc); \ src1 = read_u8(vm, code, vm->pc); \
vm->pc++; \ vm->pc++; \
src2 = read_u8(vm, code, vm->pc); \ src2 = read_u8(vm, code, vm->pc); \
vm->pc++; \ vm->pc++; \
value = frame->registers[src1]; \ value = (type)frame->registers[src1]; \
value2 = frame->registers[src2]; \ value2 = (type)frame->registers[src2]; \
cond = !!(value op value2); \ cond = !!(value op value2); \
mask = -(u32)cond; \ mask = -(u32)cond; \
target = frame->registers[dest]; \
vm->pc = (target & mask) | (vm->pc & ~mask); \ vm->pc = (target & mask) | (vm->pc & ~mask); \
return true; \ return true; \
} while (0) } while (0)
@ -33,8 +32,8 @@
vm->pc++; \ vm->pc++; \
src2 = read_u8(vm, code, vm->pc); \ src2 = read_u8(vm, code, vm->pc); \
vm->pc++; \ vm->pc++; \
frame->registers[dest] = \ frame->registers[dest] = \
(type)frame->registers[src1] op(type) frame->registers[src2]; \ (type)frame->registers[src1] op (type)frame->registers[src2]; \
return true; \ return true; \
} while (0) } while (0)
@ -79,7 +78,7 @@ bool step_vm(VM *vm) {
return true; return true;
} }
case OP_RETURN: { case OP_RETURN: {
frame->rp = 0; /* reset register ptr */ frame->rp = 0; /* reset register ptr */
vm->pc = vm->return_stack[--vm->rp]; /* set pc to return address */ vm->pc = vm->return_stack[--vm->rp]; /* set pc to return address */
vm->mp = vm->mp =
vm->frames[vm->fp--].start; /* reset memory pointer to start vm->frames[vm->fp--].start; /* reset memory pointer to start
@ -215,9 +214,9 @@ bool step_vm(VM *vm) {
size_reg = read_u8(vm, code, vm->pc); size_reg = read_u8(vm, code, vm->pc);
vm->pc++; vm->pc++;
path_ptr = frame->registers[path_reg]; /* R0: path pointer */ path_ptr = frame->registers[path_reg]; /* R0: path pointer */
buffer_ptr = frame->registers[buffer_reg]; /* R1: buffer pointer */ buffer_ptr = frame->registers[buffer_reg]; /* R1: buffer pointer */
size = frame->registers[size_reg]; /* R2: size */ size = frame->registers[size_reg]; /* R2: size */
dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]); dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
if (dev && dev->ops->write) { if (dev && dev->ops->write) {
@ -262,7 +261,7 @@ bool step_vm(VM *vm) {
args_ptr_reg = read_u8(vm, code, vm->pc); args_ptr_reg = read_u8(vm, code, vm->pc);
vm->pc++; vm->pc++;
path_ptr = frame->registers[path_reg]; /* R0: device path */ path_ptr = frame->registers[path_reg]; /* R0: device path */
cmd = frame->registers[cmd_reg]; /* R1: ioctl command */ cmd = frame->registers[cmd_reg]; /* R1: ioctl command */
args_ptr = frame->registers[args_ptr_reg]; /* R2: args pointer */ args_ptr = frame->registers[args_ptr_reg]; /* R2: args pointer */

View File

@ -1,25 +1,31 @@
((code ((code
(label main ; 0 (label main
(load-immediate $0 1) ; 6 (load-immediate $0 1)
(push $0) ; 8 (push $0)
(load-immediate $0 1) ; 14 (load-immediate $0 1)
(push $0) ; 16 (push $0)
(call &add) ; 19 (call &add)
(pop $0) ; 21 (pop $0)
(int-to-string $1 $0) ; 24 (int-to-string $1 $0)
(load-immediate $3 &terminal-str) ; 30 (push $1)
(string-length $2 $1) ; 33 (call &println)
(syscall DEVICE-WRITE $3 $1 $2) ; 41 (halt))
(load-immediate $6 &new-line)
(string-length $7 $6)
(syscall DEVICE-WRITE $5 $6 $7)
(halt)) ; 42
(label add ; 43 (label add
(pop $0) ; 45 (pop $0)
(pop $1) ; 47 (pop $1)
(add-int $2 $1 $0) (add-int $2 $1 $0)
(push $2) (push $2)
(return))
(label println
(load-immediate $0 &terminal-str)
(load-immediate $3 &new-line)
(pop $1)
(string-length $2 $1)
(syscall DEVICE-WRITE $0 $1 $2)
(string-length $4 $3)
(syscall DEVICE-WRITE $0 $3 $4)
(return))) (return)))
(data (data
(label terminal-str "/dev/term/0") (label terminal-str "/dev/term/0")

View File

@ -5,20 +5,22 @@
(call &fib) (call &fib)
(pop $0) (pop $0)
(int-to-string $1 $0) (int-to-string $1 $0)
(load-immediate $2, &terminal-str) (load-immediate $2 &terminal-str)
(string-length $4, $3) (string-length $4 $3)
(syscall DEVICE-WRITE, $2, $1, $4) (syscall DEVICE-WRITE $2 $1 $4)
(load-immediate $11 &new-line)
(string-length $12 $11)
(syscall DEVICE-WRITE $2 $11 $12)
(halt)) (halt))
(label fib (label fib
(pop $0) (pop $0)
(load-immediate $1 2) (load-immediate $1 2)
(load $2 &base-case) (jump-lt-int &base-case $0 $1)
(jump-lt-int $2 $0 $1) (load-immediate $3 2)
(load-immediate $2 2)
(sub-int $4 $0 $3) (sub-int $4 $0 $3)
(push $4) (push $4)
(call &fib) (call &fib)
(load-immediate $2 1) (load-immediate $3 1)
(sub-int $4 $0 $3) (sub-int $4 $0 $3)
(push $4) (push $4)
(call &fib) (call &fib)
@ -26,9 +28,10 @@
(pop $5) (pop $5)
(add-int $6 $5 $4) (add-int $6 $5 $4)
(push $6) (push $6)
(return)) (return)
(label base-case (label base-case
(push $0) (push $0)
(return))) (return))))
(data (data
(label terminal-str "/dev/term/0"))) (label terminal-str "/dev/term/0")
(label new-line "\n")))