add get-arg instead of using stack (push/pop). refactor call/return to use arg based
This commit is contained in:
parent
89574d9813
commit
97ad6b5505
|
@ -70,13 +70,13 @@ int get_instruction_byte_size(ExprNode *node) {
|
||||||
const char *opname = node->token;
|
const char *opname = node->token;
|
||||||
|
|
||||||
// Simple opcodes (1 byte)
|
// Simple opcodes (1 byte)
|
||||||
if (strcmp(opname, "halt") == 0 || strcmp(opname, "return") == 0) {
|
if (strcmp(opname, "halt") == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register-based opcodes (2 bytes: opcode + register)
|
// Register-based opcodes (2 bytes: opcode + register)
|
||||||
if (strcmp(opname, "pop") == 0 || strcmp(opname, "jump-if-flag") == 0 ||
|
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;
|
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, "int-to-real") == 0 || strcmp(opname, "put-8") == 0 ||
|
||||||
strcmp(opname, "nat-to-real") == 0 || strcmp(opname, "put-16") == 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-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, "nat-to-int") == 0 || strcmp(opname, "int-to-nat") == 0 ||
|
||||||
strcmp(opname, "string-length") == 0 || strcmp(opname, "store") == 0 ||
|
strcmp(opname, "string-length") == 0 || strcmp(opname, "store") == 0 ||
|
||||||
strcmp(opname, "store-8") == 0 || strcmp(opname, "store-16") == 0 ||
|
strcmp(opname, "store-8") == 0 || strcmp(opname, "store-16") == 0 ||
|
||||||
|
@ -110,14 +110,9 @@ int get_instruction_byte_size(ExprNode *node) {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (5 bytes: 1 + 4)
|
|
||||||
if (strcmp(opname, "call") == 0) {
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load, Load-immediate (6 bytes: 1 + 1 + 4)
|
// Load, Load-immediate (6 bytes: 1 + 1 + 4)
|
||||||
if (strcmp(opname, "load") == 0 || strcmp(opname, "load-immediate") == 0 ||
|
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;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,8 +427,12 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
|
||||||
emit_opcode(vm, OP_CALL);
|
emit_opcode(vm, OP_CALL);
|
||||||
u32 addr = resolve_symbol(table, node->children[0]->token);
|
u32 addr = resolve_symbol(table, node->children[0]->token);
|
||||||
emit_u32(vm, addr);
|
emit_u32(vm, addr);
|
||||||
|
int reg = parse_register(node->children[1]->token);
|
||||||
|
emit_byte(vm, reg);
|
||||||
} else if (strcmp(opname, "return") == 0) {
|
} else if (strcmp(opname, "return") == 0) {
|
||||||
emit_opcode(vm, OP_RETURN);
|
emit_opcode(vm, OP_RETURN);
|
||||||
|
int reg = parse_register(node->children[0]->token);
|
||||||
|
emit_byte(vm, reg);
|
||||||
} else if (strcmp(opname, "load-immediate") == 0) {
|
} else if (strcmp(opname, "load-immediate") == 0) {
|
||||||
emit_opcode(vm, OP_LOAD_IMM);
|
emit_opcode(vm, OP_LOAD_IMM);
|
||||||
int reg = parse_register(node->children[0]->token);
|
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);
|
int src1 = parse_register(node->children[1]->token);
|
||||||
emit_byte(vm, dest);
|
emit_byte(vm, dest);
|
||||||
emit_byte(vm, src1);
|
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) {
|
} else if (strcmp(opname, "push") == 0) {
|
||||||
emit_opcode(vm, OP_PUSH);
|
emit_opcode(vm, OP_PUSH);
|
||||||
int reg = parse_register(node->children[0]->token);
|
int reg = parse_register(node->children[0]->token);
|
||||||
|
|
|
@ -26,6 +26,7 @@ typedef enum {
|
||||||
OP_MEMSET_8, /* memset-8 : dest <-> dest+count = src1 as u8 */
|
OP_MEMSET_8, /* memset-8 : dest <-> dest+count = src1 as u8 */
|
||||||
OP_MEMSET_16, /* memset-16 : 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_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_PUSH, /* push : push const of ref */
|
||||||
OP_POP, /* pop : pop cosnt or ref */
|
OP_POP, /* pop : pop cosnt or ref */
|
||||||
OP_REG_MOV, /* register-move : dest = src1 */
|
OP_REG_MOV, /* register-move : dest = src1 */
|
||||||
|
@ -90,6 +91,7 @@ typedef struct frame_s {
|
||||||
u32 rp; /* register pointer (last unused) */
|
u32 rp; /* register pointer (last unused) */
|
||||||
u32 start; /* start and end of global allocated block */
|
u32 start; /* start and end of global allocated block */
|
||||||
u32 end;
|
u32 end;
|
||||||
|
u8 return_reg;
|
||||||
} Frame;
|
} Frame;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
36
src/vm/str.c
36
src/vm/str.c
|
@ -43,6 +43,42 @@ u32 strnlength(const char *str, u32 max_len) {
|
||||||
return i;
|
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) */
|
/* Static digit lookup table (0-9) */
|
||||||
const char digits[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
const char digits[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||||
|
|
|
@ -7,6 +7,8 @@ bool streq(const char *s1, const char *s2);
|
||||||
i32 strcopy(char* to, const char *from, u32 length);
|
i32 strcopy(char* to, const char *from, u32 length);
|
||||||
u32 strlength(const char *str);
|
u32 strlength(const char *str);
|
||||||
u32 strnlength(const char *str, u32 max_len);
|
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 uint_to_string(u32 value, char *buffer);
|
||||||
void int_to_string(i32 value, char *buffer);
|
void int_to_string(i32 value, char *buffer);
|
||||||
void fixed_to_string(i32 value, char *buffer);
|
void fixed_to_string(i32 value, char *buffer);
|
||||||
|
|
26
src/vm/vm.c
26
src/vm/vm.c
|
@ -67,7 +67,7 @@ u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) {
|
||||||
* Step to the next opcode in the vm.
|
* Step to the next opcode in the vm.
|
||||||
*/
|
*/
|
||||||
bool step_vm(VM *vm) {
|
bool step_vm(VM *vm) {
|
||||||
u16 opcode, dest, src1, src2;
|
i16 opcode, dest, src1, src2;
|
||||||
u32 v, ptr;
|
u32 v, ptr;
|
||||||
i32 value;
|
i32 value;
|
||||||
Frame *frame;
|
Frame *frame;
|
||||||
|
@ -83,6 +83,11 @@ bool step_vm(VM *vm) {
|
||||||
case OP_CALL: {
|
case OP_CALL: {
|
||||||
u32 jmp = read_u32(vm, code, vm->pc); /* location of function in code */
|
u32 jmp = read_u32(vm, code, vm->pc); /* location of function in code */
|
||||||
vm->pc += 4;
|
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->return_stack[vm->rp++] = vm->pc; /* set return address */
|
||||||
vm->fp++; /* increment to the next free frame */
|
vm->fp++; /* increment to the next free frame */
|
||||||
vm->frames[vm->fp].start = vm->mp; /* set start of new memory block */
|
vm->frames[vm->fp].start = vm->mp; /* set start of new memory block */
|
||||||
|
@ -90,7 +95,13 @@ bool step_vm(VM *vm) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_RETURN: {
|
case OP_RETURN: {
|
||||||
|
Frame *parent = &vm->frames[vm->fp - 1];
|
||||||
frame->rp = 0; /* reset register ptr */
|
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->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
|
||||||
|
@ -137,7 +148,6 @@ bool step_vm(VM *vm) {
|
||||||
write_u32(vm, memory, i, value);
|
write_u32(vm, memory, i, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->registers[0] = dest;
|
|
||||||
vm->flag = 1;
|
vm->flag = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +179,6 @@ bool step_vm(VM *vm) {
|
||||||
write_u16(vm, memory, i, value);
|
write_u16(vm, memory, i, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->registers[0] = dest;
|
|
||||||
vm->flag = 1;
|
vm->flag = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +210,6 @@ bool step_vm(VM *vm) {
|
||||||
write_u8(vm, memory, i, value);
|
write_u8(vm, memory, i, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->registers[0] = dest;
|
|
||||||
vm->flag = 1;
|
vm->flag = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -334,6 +342,16 @@ bool step_vm(VM *vm) {
|
||||||
write_u8(vm, memory, ptr, v8);
|
write_u8(vm, memory, ptr, v8);
|
||||||
return true;
|
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: {
|
case OP_PUSH: {
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
(module add
|
((code
|
||||||
(const terminal-namespace "/dev/term/0")
|
(label main
|
||||||
(const new-line "\n")
|
|
||||||
|
|
||||||
(fn :1 main ()
|
|
||||||
(load-immediate $0 1)
|
(load-immediate $0 1)
|
||||||
(load-immediate $1 1)
|
(call &add $0)
|
||||||
(call &add ($0 $1) $2)
|
(int-to-string $1 $0)
|
||||||
(int-to-string $1 $2)
|
(call &println nil)
|
||||||
(call &pln ($1))
|
|
||||||
(halt))
|
(halt))
|
||||||
|
|
||||||
(fn :1 add ($0 $1)
|
(label add
|
||||||
|
(get-arg $0 $0)
|
||||||
|
(get-arg $1 $0)
|
||||||
(add-int $2 $1 $0)
|
(add-int $2 $1 $0)
|
||||||
(return $2))
|
(return $2))
|
||||||
|
|
||||||
(fn :1 pln ($1)
|
(label println
|
||||||
(load-immediate $0 &terminal-namespace)
|
(load-immediate $0 &terminal-namespace)
|
||||||
(load-immediate $3 &new-line)
|
(load-immediate $3 &new-line)
|
||||||
|
(get-arg $1 $1)
|
||||||
(string-length $2 $1)
|
(string-length $2 $1)
|
||||||
(syscall WRITE $0 $1 $2)
|
(syscall WRITE $0 $1 $2)
|
||||||
(string-length $4 $3)
|
(string-length $4 $3)
|
||||||
(syscall WRITE $0 $3 $4)
|
(syscall WRITE $0 $3 $4)
|
||||||
(return)))
|
(return nil)))
|
||||||
|
(data
|
||||||
|
(label terminal-namespace "/dev/term/0")
|
||||||
|
(label new-line "\n")))
|
||||||
|
|
Loading…
Reference in New Issue