add get-arg instead of using stack (push/pop). refactor call/return to use arg based

This commit is contained in:
zongor 2025-10-11 13:01:40 -07:00
parent 89574d9813
commit 97ad6b5505
6 changed files with 91 additions and 26 deletions

View File

@ -70,13 +70,13 @@ int get_instruction_byte_size(ExprNode *node) {
const char *opname = node->token;
// Simple opcodes (1 byte)
if (strcmp(opname, "halt") == 0 || strcmp(opname, "return") == 0) {
if (strcmp(opname, "halt") == 0) {
return 1;
}
// Register-based opcodes (2 bytes: opcode + register)
if (strcmp(opname, "pop") == 0 || strcmp(opname, "jump-if-flag") == 0 ||
strcmp(opname, "jump") == 0 || strcmp(opname, "push") == 0) {
strcmp(opname, "jump") == 0 || strcmp(opname, "push") == 0 || strcmp(opname, "return") == 0) {
return 2;
}
@ -86,7 +86,7 @@ int get_instruction_byte_size(ExprNode *node) {
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, "real-to-nat") == 0 || strcmp(opname, "get-arg") == 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 ||
@ -110,14 +110,9 @@ int get_instruction_byte_size(ExprNode *node) {
return 4;
}
// (5 bytes: 1 + 4)
if (strcmp(opname, "call") == 0) {
return 5;
}
// Load, Load-immediate (6 bytes: 1 + 1 + 4)
if (strcmp(opname, "load") == 0 || strcmp(opname, "load-immediate") == 0 ||
strcmp(opname, "load-16") == 0 || strcmp(opname, "load-8") == 0) {
strcmp(opname, "load-16") == 0 || strcmp(opname, "load-8") == 0 || strcmp(opname, "call") == 0) {
return 6;
}
@ -432,8 +427,12 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
emit_opcode(vm, OP_CALL);
u32 addr = resolve_symbol(table, node->children[0]->token);
emit_u32(vm, addr);
int reg = parse_register(node->children[1]->token);
emit_byte(vm, reg);
} else if (strcmp(opname, "return") == 0) {
emit_opcode(vm, OP_RETURN);
int reg = parse_register(node->children[0]->token);
emit_byte(vm, reg);
} else if (strcmp(opname, "load-immediate") == 0) {
emit_opcode(vm, OP_LOAD_IMM);
int reg = parse_register(node->children[0]->token);
@ -524,6 +523,12 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
int src1 = parse_register(node->children[1]->token);
emit_byte(vm, dest);
emit_byte(vm, src1);
} else if (strcmp(opname, "get-arg") == 0) {
emit_opcode(vm, OP_GET_ARG);
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, "push") == 0) {
emit_opcode(vm, OP_PUSH);
int reg = parse_register(node->children[0]->token);

View File

@ -26,6 +26,7 @@ typedef enum {
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_GET_ARG, /* get-arg : this.dest_reg = parent.src_reg */
OP_PUSH, /* push : push const of ref */
OP_POP, /* pop : pop cosnt or ref */
OP_REG_MOV, /* register-move : dest = src1 */
@ -90,6 +91,7 @@ typedef struct frame_s {
u32 rp; /* register pointer (last unused) */
u32 start; /* start and end of global allocated block */
u32 end;
u8 return_reg;
} Frame;
typedef enum {

View File

@ -43,6 +43,42 @@ u32 strnlength(const char *str, u32 max_len) {
return i;
}
void *memcopy(void *dest, const void *src, u32 n) {
u8 *d = (u8 *)dest;
const u8 *s = (const u8 *)src;
while (n >= sizeof(u32) &&
(((uintptr_t)d & 3) == 0) &&
(((uintptr_t)s & 3) == 0)) {
*(u32 *)d = *(u32 *)s;
d += sizeof(u32);
s += sizeof(u32);
n -= sizeof(u32);
}
while (n--) {
*d++ = *s++;
}
return dest;
}
void *memmov(void *dest, const void *src, u32 n) {
u8 *d = (u8 *)dest;
const u8 *s = (const u8 *)src;
if (d < s) {
return memcopy(dest, src, n);
} else if (d > s) {
d += n;
s += n;
while (n--) {
*--d = *--s;
}
}
return dest;
}
/* Static digit lookup table (0-9) */
const char digits[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

View File

@ -7,6 +7,8 @@ bool streq(const char *s1, const char *s2);
i32 strcopy(char* to, const char *from, u32 length);
u32 strlength(const char *str);
u32 strnlength(const char *str, u32 max_len);
void *memcopy(void *dest, const void *src, u32 n);
void *memmov(void *dest, const void *src, u32 n);
void uint_to_string(u32 value, char *buffer);
void int_to_string(i32 value, char *buffer);
void fixed_to_string(i32 value, char *buffer);

View File

@ -67,7 +67,7 @@ u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) {
* Step to the next opcode in the vm.
*/
bool step_vm(VM *vm) {
u16 opcode, dest, src1, src2;
i16 opcode, dest, src1, src2;
u32 v, ptr;
i32 value;
Frame *frame;
@ -83,6 +83,11 @@ bool step_vm(VM *vm) {
case OP_CALL: {
u32 jmp = read_u32(vm, code, vm->pc); /* location of function in code */
vm->pc += 4;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
if (src1 >= 0) {
frame->return_reg = src1;
}
vm->return_stack[vm->rp++] = vm->pc; /* set return address */
vm->fp++; /* increment to the next free frame */
vm->frames[vm->fp].start = vm->mp; /* set start of new memory block */
@ -90,7 +95,13 @@ bool step_vm(VM *vm) {
return true;
}
case OP_RETURN: {
Frame *parent = &vm->frames[vm->fp - 1];
frame->rp = 0; /* reset register ptr */
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
if (src1 >= 0) {
parent->registers[parent->return_reg] = frame->registers[src1];
}
vm->pc = vm->return_stack[--vm->rp]; /* set pc to return address */
vm->mp =
vm->frames[vm->fp--].start; /* reset memory pointer to start
@ -137,7 +148,6 @@ bool step_vm(VM *vm) {
write_u32(vm, memory, i, value);
}
frame->registers[0] = dest;
vm->flag = 1;
return true;
}
@ -169,7 +179,6 @@ bool step_vm(VM *vm) {
write_u16(vm, memory, i, value);
}
frame->registers[0] = dest;
vm->flag = 1;
return true;
}
@ -201,7 +210,6 @@ bool step_vm(VM *vm) {
write_u8(vm, memory, i, value);
}
frame->registers[0] = dest;
vm->flag = 1;
return true;
}
@ -334,6 +342,16 @@ bool step_vm(VM *vm) {
write_u8(vm, memory, ptr, v8);
return true;
}
case OP_GET_ARG: {
Frame *parent = &vm->frames[vm->fp - 1];
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
frame->registers[dest] =
parent->registers[src1];
return true;
}
case OP_PUSH: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;

View File

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