Add number tostring methods

This commit is contained in:
zongor 2026-01-11 20:33:57 -08:00
parent c1b629e368
commit 025acce1c6
3 changed files with 167 additions and 65 deletions

View File

@ -23,27 +23,43 @@ bool init_vm() {
u32 syscall(u32 id, u32 size, u32 mem_ptr) { u32 syscall(u32 id, u32 size, u32 mem_ptr) {
USED(size); USED(size);
switch(id) { switch(id) {
case SYSCALL_DBG_PRINT: { case SYSCALL_CONSOLE_WRITE: {
u32 val = READ_U32(mem_ptr); u32 size = *(u32 *)(mem + mem_ptr);
printf("%d\n", val); u32 ptr = mem_ptr + 4;
return 0; 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 return 1; // generic error
} }
void test_add_two_num() { void test_add_two_num() {
i32 main_local_count = 4; i32 main_local_count = 5;
mp += (4 * main_local_count); mp += (4 * main_local_count);
code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 1); code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 1);
code[cp++] = ENCODE_B(OP_PUSH, 0, 0); code[cp++] = ENCODE_B(OP_PUSH, 0, 0);
code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, 1); code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, 1);
code[cp++] = ENCODE_B(OP_PUSH, 1, 0); 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_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); code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0);
/* add */ /* add */
@ -52,10 +68,10 @@ void test_add_two_num() {
} }
void test_fibonacci() { void test_fibonacci() {
i32 fib = 6; i32 fib = 7;
i32 base_case = 20; i32 base_case = 21;
/* function main() */ /* function main() */
i32 main_local_count = 3; i32 main_local_count = 4;
mp += (4 * main_local_count); mp += (4 * main_local_count);
/* fib(35) */ /* fib(35) */
code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 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_B(OP_LOAD_IMM, 1, fib);
code[cp++] = ENCODE_A(OP_CALL, 1, 9, 2); code[cp++] = ENCODE_A(OP_CALL, 1, 9, 2);
/* print */ /* 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); code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0);
/* function fib (int n) int */ /* function fib (int n) int */
//code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_DBG_PRINT, 1, 0); //code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_DBG_PRINT, 1, 0);

183
vm/vm.c
View File

@ -11,6 +11,24 @@ u8 interrupt; /* device interrupt */
u32 *code; /* code */ u32 *code; /* code */
u8 *mem; /* memory */ 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() { bool step_vm() {
u32 instruction = code[pc++]; u32 instruction = code[pc++];
@ -157,15 +175,11 @@ bool step_vm() {
} }
case OP_MEM_ALLOC: { case OP_MEM_ALLOC: {
DECODE_A(instruction) DECODE_A(instruction)
u32 size, ldest; u32 size = locals[src1];
u32 rd = fp + (dest * 4); locals[dest] = mp;
u32 r1 = fp + (src1 * 4);
USED(src2);
ldest = READ_U32(rd);
WRITE_U32(ldest, mp);
size = READ_U32(r1);
WRITE_U32(mp, size); WRITE_U32(mp, size);
mp += (4 * (size + 4)); USED(src2);
mp += (size + 4);
return true; return true;
} }
case OP_MEM_CPY_8: { case OP_MEM_CPY_8: {
@ -292,22 +306,18 @@ bool step_vm() {
DECODE_A(instruction) DECODE_A(instruction)
u32 i, start, end; u32 i, start, end;
u32 rd = fp + (dest * 4); u32 value = locals[src1];
u32 r1 = fp + (src1 * 4); u32 count = locals[src2];
u32 r2 = fp + (src2 * 4);
u32 value = READ_U32(r1); if (count == 0) {
u32 count = READ_U32(r2);
if (r2 == 0) {
status = 1; status = 1;
return true; return true;
} }
start = READ_U32(rd); start = READ_U32(locals[dest]);
end = start + count; end = start + count;
if (start >= mp || r2 > mp || end > mp) { if (start >= mp || count > mp || end > mp) {
status = 1; status = 1;
return true; return true;
} }
@ -321,11 +331,8 @@ bool step_vm() {
} }
case OP_MOV: { case OP_MOV: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4);
u32 r1 = fp + (src1 * 4);
u32 value = READ_U32(r1);
USED(src2); USED(src2);
WRITE_U32(rd, value); locals[dest] = locals[src1];
return true; return true;
} }
case OP_ADD_INT: { case OP_ADD_INT: {
@ -393,56 +400,44 @@ bool step_vm() {
} }
case OP_INT_TO_REAL: { case OP_INT_TO_REAL: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4); i32 result = (i32)locals[src1] << 16;
u32 r1 = fp + (src1 * 4);
i32 result = (i32)READ_U32(r1) << 16;
USED(src2); USED(src2);
WRITE_U32(rd, result); locals[dest] = result;
return true; return true;
} }
case OP_INT_TO_NAT: { case OP_INT_TO_NAT: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4); u32 result = (u32)locals[src1];
u32 r1 = fp + (src1 * 4);
u32 result = (u32)READ_U32(r1);
USED(src2); USED(src2);
WRITE_U32(rd, result); locals[dest] = result;
return true; return true;
} }
case OP_NAT_TO_REAL: { case OP_NAT_TO_REAL: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4); i32 result = (i32)locals[src1] << 16;
u32 r1 = fp + (src1 * 4);
i32 result = ((i32)READ_U32(r1) << 16);
USED(src2); USED(src2);
WRITE_U32(rd, result); locals[dest] = result;
return true; return true;
} }
case OP_NAT_TO_INT: { case OP_NAT_TO_INT: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4); i32 result = (i32)locals[src1];
u32 r1 = fp + (src1 * 4);
i32 result = ((i32)READ_U32(r1));
USED(src2); USED(src2);
WRITE_U32(rd, result); locals[dest] = result;
return true; return true;
} }
case OP_REAL_TO_INT: { case OP_REAL_TO_INT: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4); i32 result = (i32)locals[src1] >> 16;
u32 r1 = fp + (src1 * 4);
i32 result = ((i32)READ_U32(r1) >> 16);
USED(src2); USED(src2);
WRITE_U32(rd, result); locals[dest] = result;
return true; return true;
} }
case OP_REAL_TO_NAT: { case OP_REAL_TO_NAT: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4); u32 result = (u32)locals[src1] >> 16;
u32 r1 = fp + (src1 * 4);
u32 result = ((u32)READ_U32(r1) >> 16);
USED(src2); USED(src2);
WRITE_U32(rd, result); locals[dest] = result;
return true; return true;
} }
case OP_BIT_SHIFT_LEFT: { case OP_BIT_SHIFT_LEFT: {
@ -470,8 +465,7 @@ bool step_vm() {
} }
case OP_JMP_ABS: { case OP_JMP_ABS: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4); u32 jmp_dest = locals[dest];
u32 jmp_dest = READ_U32(rd);
if (jmp_dest > cp) { if (jmp_dest > cp) {
status = 1; status = 1;
return true; return true;
@ -484,10 +478,7 @@ bool step_vm() {
} }
case OP_JMP_OFF: { case OP_JMP_OFF: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4); u32 jmp_dest = locals[dest] + locals[src1];
u32 r1 = fp + (src1 * 4);
u32 jmp_dest = READ_U32(rd) + READ_U32(r1);
if (jmp_dest > cp) { if (jmp_dest > cp) {
status = 1; status = 1;
return true; return true;
@ -565,6 +556,96 @@ bool step_vm() {
} }
case OP_JLE_REAL: { case OP_JLE_REAL: {
COMPARE_AND_JUMP(i32, <=); 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;
} }
} }

View File

@ -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_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_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_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 */ OP_MAX_OPCODE /* not an opcode count of instructions */
} Opcode; } Opcode;
typedef enum { typedef enum {
SYSCALL_DBG_PRINT, /* temporary debugging print, use tunnel later */ SYSCALL_CONSOLE_WRITE,
SYSCALL_CONSOLE_READ,
SYSCALL_MAX SYSCALL_MAX
} Syscall; } Syscall;