add and fibbonacci examples now working
This commit is contained in:
parent
77745c8880
commit
f650e8110b
|
@ -11,16 +11,24 @@ i32 console_open(void *data, u32 mode) {
|
|||
|
||||
i32 console_read(void *data, u8 *buffer, u32 size) {
|
||||
USED(data);
|
||||
ssize_t result = read(STDIN_FILENO, buffer, size);
|
||||
if (result < 0) return -1; /* Error */
|
||||
return (i32)result; /* Bytes read */
|
||||
for (u32 i = 0; i < size; i++) {
|
||||
u8 ch = getchar();
|
||||
if (ch == '\0')
|
||||
break;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
buffer[i] = ch;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
i32 console_write(void *data, const u8 *buffer, u32 size) {
|
||||
USED(data);
|
||||
ssize_t result = write(STDOUT_FILENO, buffer, size);
|
||||
if (result < 0) return -1; /* Error */
|
||||
return (i32)result; /* Bytes written */
|
||||
for (u32 i = 0; i < size; i++) {
|
||||
putchar(buffer[i]);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
i32 console_close(void *data) {
|
||||
|
|
|
@ -227,6 +227,73 @@ void register_sdl_devices(VM *vm) {
|
|||
&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[]) {
|
||||
struct CompilerConfig config = {0};
|
||||
|
||||
|
@ -352,6 +419,7 @@ i32 main(i32 argc, char *argv[]) {
|
|||
}
|
||||
} else {
|
||||
while (running) {
|
||||
//printf("| %d %s %d\n", vm.code[vm.pc], opcode_to_string(vm.code[vm.pc]), vm.pc);
|
||||
running = step_vm(&vm);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ Symbol *symbol_table_lookup(SymbolTable *table, const char *name) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Add this helper for your current code
|
||||
u32 find_label_in_table(SymbolTable *table, const char *name) {
|
||||
Symbol *sym = symbol_table_lookup(table, name);
|
||||
if (!sym) {
|
||||
|
@ -77,39 +76,71 @@ int get_instruction_byte_size(ExprNode *node) {
|
|||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Load/store with register and address (5 bytes: 1 + 1 + 4)
|
||||
if (strcmp(opname, "load") == 0 || strcmp(opname, "store") == 0 ||
|
||||
strcmp(opname, "jump") == 0 || strcmp(opname, "jump-if-flag") == 0 ||
|
||||
strcmp(opname, "call") == 0) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Load-immediate (5 bytes: 1 + 1 + 4)
|
||||
if (strcmp(opname, "load-immediate") == 0) {
|
||||
// Load, Load-immediate (5 bytes: 1 + 1 + 4)
|
||||
if (strcmp(opname, "load-immediate") == 0 || strcmp(opname, "load") == 0 ||
|
||||
strcmp(opname, "store") == 0) {
|
||||
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)
|
||||
if (strcmp(opname, "syscall") == 0) {
|
||||
return 1 + 4 + (node->child_count > 0 ? node->child_count - 1 : 0);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown opcode for sizing: %s\n", opname);
|
||||
return 4; // Conservative fallback
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
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++)
|
||||
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 (node->child_count >= 1) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -141,7 +172,8 @@ void collect_symbols_in_node(SymbolTable *table, ExprNode *node,
|
|||
} else {
|
||||
int size = get_instruction_byte_size(node);
|
||||
*current_addr += size;
|
||||
printf("%s +%d bytes -> %d\n", indent, size, *current_addr);
|
||||
//printf(" +%d bytes -> %d\n", size, *current_addr);
|
||||
//printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,8 +98,8 @@ typedef struct device_s {
|
|||
u32 flags; /* permissions, status, etc. */
|
||||
} Device;
|
||||
|
||||
#define MEMORY_SIZE 1024 /*(640 * 480 + 65536)*/
|
||||
#define CODE_SIZE 128 /*8192*/
|
||||
#define MEMORY_SIZE (640 * 480 + 65536)
|
||||
#define CODE_SIZE 8192
|
||||
#define FRAMES_SIZE 128
|
||||
#define STACK_SIZE 256
|
||||
#define DEVICES_SIZE 8
|
||||
|
@ -111,7 +111,7 @@ typedef struct vm_s {
|
|||
u32 rp; /* return stack pointer (top of stack) */
|
||||
u32 mp; /* memory pointer (last allocated value) */
|
||||
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 */
|
||||
u32 stack[STACK_SIZE]; /* main stack */
|
||||
u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */
|
||||
|
|
23
src/vm/vm.c
23
src/vm/vm.c
|
@ -7,20 +7,19 @@
|
|||
do { \
|
||||
i32 cond; \
|
||||
u32 mask, target; \
|
||||
u8 dest, src1, src2; \
|
||||
u8 src1, src2; \
|
||||
type value; \
|
||||
type value2; \
|
||||
dest = read_u8(vm, code, vm->pc); \
|
||||
vm->pc++; \
|
||||
target = read_u32(vm, code, vm->pc); \
|
||||
vm->pc+=4; \
|
||||
src1 = read_u8(vm, code, vm->pc); \
|
||||
vm->pc++; \
|
||||
src2 = read_u8(vm, code, vm->pc); \
|
||||
vm->pc++; \
|
||||
value = frame->registers[src1]; \
|
||||
value2 = frame->registers[src2]; \
|
||||
value = (type)frame->registers[src1]; \
|
||||
value2 = (type)frame->registers[src2]; \
|
||||
cond = !!(value op value2); \
|
||||
mask = -(u32)cond; \
|
||||
target = frame->registers[dest]; \
|
||||
vm->pc = (target & mask) | (vm->pc & ~mask); \
|
||||
return true; \
|
||||
} while (0)
|
||||
|
@ -33,8 +32,8 @@
|
|||
vm->pc++; \
|
||||
src2 = read_u8(vm, code, vm->pc); \
|
||||
vm->pc++; \
|
||||
frame->registers[dest] = \
|
||||
(type)frame->registers[src1] op(type) frame->registers[src2]; \
|
||||
frame->registers[dest] = \
|
||||
(type)frame->registers[src1] op (type)frame->registers[src2]; \
|
||||
return true; \
|
||||
} while (0)
|
||||
|
||||
|
@ -79,7 +78,7 @@ bool step_vm(VM *vm) {
|
|||
return true;
|
||||
}
|
||||
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->mp =
|
||||
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);
|
||||
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 */
|
||||
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]);
|
||||
if (dev && dev->ops->write) {
|
||||
|
@ -262,7 +261,7 @@ bool step_vm(VM *vm) {
|
|||
args_ptr_reg = read_u8(vm, code, 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 */
|
||||
args_ptr = frame->registers[args_ptr_reg]; /* R2: args pointer */
|
||||
|
||||
|
|
|
@ -1,25 +1,31 @@
|
|||
((code
|
||||
(label main ; 0
|
||||
(load-immediate $0 1) ; 6
|
||||
(push $0) ; 8
|
||||
(load-immediate $0 1) ; 14
|
||||
(push $0) ; 16
|
||||
(call &add) ; 19
|
||||
(pop $0) ; 21
|
||||
(int-to-string $1 $0) ; 24
|
||||
(load-immediate $3 &terminal-str) ; 30
|
||||
(string-length $2 $1) ; 33
|
||||
(syscall DEVICE-WRITE $3 $1 $2) ; 41
|
||||
(load-immediate $6 &new-line)
|
||||
(string-length $7 $6)
|
||||
(syscall DEVICE-WRITE $5 $6 $7)
|
||||
(halt)) ; 42
|
||||
(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 ; 43
|
||||
(pop $0) ; 45
|
||||
(pop $1) ; 47
|
||||
(label add
|
||||
(pop $0)
|
||||
(pop $1)
|
||||
(add-int $2 $1 $0)
|
||||
(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)))
|
||||
(data
|
||||
(label terminal-str "/dev/term/0")
|
||||
|
|
|
@ -5,20 +5,22 @@
|
|||
(call &fib)
|
||||
(pop $0)
|
||||
(int-to-string $1 $0)
|
||||
(load-immediate $2, &terminal-str)
|
||||
(string-length $4, $3)
|
||||
(syscall DEVICE-WRITE, $2, $1, $4)
|
||||
(load-immediate $2 &terminal-str)
|
||||
(string-length $4 $3)
|
||||
(syscall DEVICE-WRITE $2 $1 $4)
|
||||
(load-immediate $11 &new-line)
|
||||
(string-length $12 $11)
|
||||
(syscall DEVICE-WRITE $2 $11 $12)
|
||||
(halt))
|
||||
(label fib
|
||||
(pop $0)
|
||||
(load-immediate $1 2)
|
||||
(load $2 &base-case)
|
||||
(jump-lt-int $2 $0 $1)
|
||||
(load-immediate $2 2)
|
||||
(jump-lt-int &base-case $0 $1)
|
||||
(load-immediate $3 2)
|
||||
(sub-int $4 $0 $3)
|
||||
(push $4)
|
||||
(call &fib)
|
||||
(load-immediate $2 1)
|
||||
(load-immediate $3 1)
|
||||
(sub-int $4 $0 $3)
|
||||
(push $4)
|
||||
(call &fib)
|
||||
|
@ -26,9 +28,10 @@
|
|||
(pop $5)
|
||||
(add-int $6 $5 $4)
|
||||
(push $6)
|
||||
(return))
|
||||
(label base-case
|
||||
(push $0)
|
||||
(return)))
|
||||
(return)
|
||||
(label base-case
|
||||
(push $0)
|
||||
(return))))
|
||||
(data
|
||||
(label terminal-str "/dev/term/0")))
|
||||
(label terminal-str "/dev/term/0")
|
||||
(label new-line "\n")))
|
||||
|
|
Loading…
Reference in New Issue