diff --git a/arch/linux/tui/main.c b/arch/linux/tui/main.c index cc5afb7..8380d02 100644 --- a/arch/linux/tui/main.c +++ b/arch/linux/tui/main.c @@ -23,27 +23,43 @@ bool init_vm() { u32 syscall(u32 id, u32 size, u32 mem_ptr) { USED(size); switch(id) { - case SYSCALL_DBG_PRINT: { - u32 val = READ_U32(mem_ptr); - printf("%d\n", val); - return 0; - } + case SYSCALL_CONSOLE_WRITE: { + u32 size = *(u32 *)(mem + mem_ptr); + u32 ptr = mem_ptr + 4; + for (u32 i = 0; i < size; i++) { + putchar(mem[ptr + i]); + } + putchar('\n'); + return 0; + } + case SYSCALL_CONSOLE_READ: { + for (u32 i = 0; i < size; i++) { + u8 ch = getchar(); + if (ch == '\0') + break; + if (ch == '\n') + break; + mem[mem_ptr + i] = ch; + } + } } return 1; // generic error } void test_add_two_num() { - i32 main_local_count = 4; + i32 main_local_count = 5; mp += (4 * main_local_count); code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 1); code[cp++] = ENCODE_B(OP_PUSH, 0, 0); code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, 1); code[cp++] = ENCODE_B(OP_PUSH, 1, 0); - i32 add = cp + 4; + i32 add = cp + 5; code[cp++] = ENCODE_B(OP_LOAD_IMM, 2, add); - code[cp++] = ENCODE_A(OP_CALL, 2, 3, 3); - code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_DBG_PRINT, 1, 3); + + code[cp++] = ENCODE_A(OP_CALL, 2, 3, 0); + code[cp++] = ENCODE_A(OP_INT_TO_STR, 4, 3, 0); + code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 4); code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0); /* add */ @@ -52,10 +68,10 @@ void test_add_two_num() { } void test_fibonacci() { - i32 fib = 6; - i32 base_case = 20; + i32 fib = 7; + i32 base_case = 21; /* function main() */ - i32 main_local_count = 3; + i32 main_local_count = 4; mp += (4 * main_local_count); /* fib(35) */ code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 35); @@ -63,7 +79,8 @@ void test_fibonacci() { code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, fib); code[cp++] = ENCODE_A(OP_CALL, 1, 9, 2); /* print */ - code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_DBG_PRINT, 1, 2); + code[cp++] = ENCODE_A(OP_INT_TO_STR, 3, 2, 0); + code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 3); code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0); /* function fib (int n) int */ //code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_DBG_PRINT, 1, 0); diff --git a/vm/vm.c b/vm/vm.c index 7d3f19b..ac88096 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -11,6 +11,24 @@ u8 interrupt; /* device interrupt */ u32 *code; /* code */ u8 *mem; /* memory */ +#define MAX_LEN_INT32 11 +#define MAX_INT32 2147483647 +#define MIN_INT32 -2147483648 +const char radix_set[11] = "0123456789"; + +u32 str_alloc(const char *str, u32 length) { + u32 str_addr = mp; + u32 i = 0; + mp += 4; + while (i < length) { + mem[mp++] = str[i++]; + } + mem[mp++] = '\0'; + + WRITE_U32(str_addr, length); + return str_addr; +} + bool step_vm() { u32 instruction = code[pc++]; @@ -157,15 +175,11 @@ bool step_vm() { } case OP_MEM_ALLOC: { DECODE_A(instruction) - u32 size, ldest; - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - USED(src2); - ldest = READ_U32(rd); - WRITE_U32(ldest, mp); - size = READ_U32(r1); + u32 size = locals[src1]; + locals[dest] = mp; WRITE_U32(mp, size); - mp += (4 * (size + 4)); + USED(src2); + mp += (size + 4); return true; } case OP_MEM_CPY_8: { @@ -292,22 +306,18 @@ bool step_vm() { DECODE_A(instruction) u32 i, start, end; - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - u32 r2 = fp + (src2 * 4); + u32 value = locals[src1]; + u32 count = locals[src2]; - u32 value = READ_U32(r1); - u32 count = READ_U32(r2); - - if (r2 == 0) { + if (count == 0) { status = 1; return true; } - start = READ_U32(rd); + start = READ_U32(locals[dest]); end = start + count; - if (start >= mp || r2 > mp || end > mp) { + if (start >= mp || count > mp || end > mp) { status = 1; return true; } @@ -321,11 +331,8 @@ bool step_vm() { } case OP_MOV: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - u32 value = READ_U32(r1); USED(src2); - WRITE_U32(rd, value); + locals[dest] = locals[src1]; return true; } case OP_ADD_INT: { @@ -393,56 +400,44 @@ bool step_vm() { } case OP_INT_TO_REAL: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - i32 result = (i32)READ_U32(r1) << 16; + i32 result = (i32)locals[src1] << 16; USED(src2); - WRITE_U32(rd, result); + locals[dest] = result; return true; } case OP_INT_TO_NAT: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - u32 result = (u32)READ_U32(r1); + u32 result = (u32)locals[src1]; USED(src2); - WRITE_U32(rd, result); + locals[dest] = result; return true; } case OP_NAT_TO_REAL: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - i32 result = ((i32)READ_U32(r1) << 16); + i32 result = (i32)locals[src1] << 16; USED(src2); - WRITE_U32(rd, result); + locals[dest] = result; return true; } case OP_NAT_TO_INT: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - i32 result = ((i32)READ_U32(r1)); + i32 result = (i32)locals[src1]; USED(src2); - WRITE_U32(rd, result); + locals[dest] = result; return true; } case OP_REAL_TO_INT: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - i32 result = ((i32)READ_U32(r1) >> 16); + i32 result = (i32)locals[src1] >> 16; USED(src2); - WRITE_U32(rd, result); + locals[dest] = result; return true; } case OP_REAL_TO_NAT: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - u32 result = ((u32)READ_U32(r1) >> 16); + u32 result = (u32)locals[src1] >> 16; USED(src2); - WRITE_U32(rd, result); + locals[dest] = result; return true; } case OP_BIT_SHIFT_LEFT: { @@ -470,8 +465,7 @@ bool step_vm() { } case OP_JMP_ABS: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 jmp_dest = READ_U32(rd); + u32 jmp_dest = locals[dest]; if (jmp_dest > cp) { status = 1; return true; @@ -484,10 +478,7 @@ bool step_vm() { } case OP_JMP_OFF: { DECODE_A(instruction) - u32 rd = fp + (dest * 4); - u32 r1 = fp + (src1 * 4); - - u32 jmp_dest = READ_U32(rd) + READ_U32(r1); + u32 jmp_dest = locals[dest] + locals[src1]; if (jmp_dest > cp) { status = 1; return true; @@ -565,6 +556,96 @@ bool step_vm() { } case OP_JLE_REAL: { COMPARE_AND_JUMP(i32, <=); + } + case OP_INT_TO_STR: { + DECODE_A(instruction) + + u32 i = MAX_LEN_INT32; + i32 v = (i32)locals[src1]; + char buffer[MAX_LEN_INT32]; + i32 n = v; + bool neg = n < 0; + USED(src2); + + if (neg) + n = -n; + + do { + buffer[--i] = radix_set[n % 10]; + n /= 10; + } while (n > 0); + if (neg) + buffer[--i] = '-'; + /* Ensure at least one digit is written for 0 */ + if (v == 0) + buffer[--i] = '0'; + + /* Copy from buffer[i] to buffer + MAX_LEN_INT32 */ + locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i); + + return pc; + } + case OP_NAT_TO_STR: { + DECODE_A(instruction) + + u32 v = (i32)locals[src1]; + char buffer[MAX_LEN_INT32]; + u32 n = v; + u32 i = MAX_LEN_INT32; + USED(src2); + do { + buffer[--i] = radix_set[n % 10]; + n /= 10; + } while (n > 0); + /* Ensure at least one digit is written for 0 */ + if (v == 0) + buffer[--i] = '0'; + /* Copy from buffer[i] to buffer + MAX_LEN_INT32 */ + locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i); + + return pc; + } + case OP_REAL_TO_STR: { + DECODE_A(instruction) + + u32 i = 0, j = 0; + i32 q = (i32)locals[src1]; + char buffer[MAX_LEN_INT32]; + u32 int_part, frac_part; + + if (q < 0) { + buffer[i++] = '-'; + q = -q; + } + + int_part = q >> 16; + frac_part = q & 0xFFFF; + USED(src2); + + if (int_part == 0) { + buffer[i++] = radix_set[0]; + } else { + char tmp[16]; + i32 tmp_i = 0; + while (int_part > 0) { + tmp[tmp_i++] = radix_set[int_part % 10]; + int_part /= 10; + } + while (tmp_i > 0) { + buffer[i++] = tmp[--tmp_i]; + } + } + + buffer[i++] = '.'; + for (j = 0; j < 6; j++) { + frac_part *= 10; + buffer[i++] = radix_set[frac_part >> 16]; + frac_part &= 0xFFFF; + } + + locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i); + + return pc; } } diff --git a/vm/vm.h b/vm/vm.h index 512e580..4dcae6e 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -115,11 +115,15 @@ typedef enum { OP_JGT_REAL, /* jump_gt_real : A : jump to locals[dest] if locals[src1] as real > locals[src2] as real */ OP_JLT_REAL, /* jump_lt_real : A : jump to locals[dest] if locals[src1] as real < locals[src2] as real */ OP_JLE_REAL, /* jump_le_real : A : jump to locals[dest] if locals[src1] as real <= locals[src2] as real */ + OP_INT_TO_STR, + OP_NAT_TO_STR, + OP_REAL_TO_STR, OP_MAX_OPCODE /* not an opcode count of instructions */ } Opcode; typedef enum { - SYSCALL_DBG_PRINT, /* temporary debugging print, use tunnel later */ + SYSCALL_CONSOLE_WRITE, + SYSCALL_CONSOLE_READ, SYSCALL_MAX } Syscall;