Add number tostring methods
This commit is contained in:
parent
c1b629e368
commit
025acce1c6
|
|
@ -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);
|
||||
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);
|
||||
|
|
|
|||
183
vm/vm.c
183
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
6
vm/vm.h
6
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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue