diff --git a/vm/vm.c b/vm/vm.c index dd1348c..8ce28b8 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -1,5 +1,7 @@ #include "vm.h" +#define FRAME_HEADER_SIZE 12 + u32 pc; /* program counter */ u32 cp; /* code pointer */ u32 mp; /* memory pointer */ @@ -20,19 +22,70 @@ bool step_vm() { return false; } case OP_CALL: { - /* DECODE_A(instruction) */ + DECODE_A(instruction) + u32 fn_ptr, local_count, return_ptr; + + u32 rd = fp + dest; + u32 r1 = fp + src1; + u32 r2 = fp + src2; + + fn_ptr = READ_U32(rd); + local_count = READ_U32(r1); + return_ptr = READ_U32(r2); + + /* push parents frame value to reset the heap to */ + WRITE_U32(mp, fp); + mp += 4; /* push return address to child frame */ + WRITE_U32(mp, pc + 1); + mp += 4; /* push local address to return the value to */ - /* push current mp value to reset the heap to */ - /* move mp by args many locals */ + WRITE_U32(mp, return_ptr); + mp += 4; + /* now set the frame pointer, where the locals start */ + fp = mp; + /* move mp by count many locals */ + mp += (4 * local_count); /* jump to dest_ptr */ + pc = fn_ptr; return true; } case OP_RETURN: { - /* DECODE_A(instruction) */ - /* copy return value to parent return local */ - /* reset mp to saved mp */ + DECODE_B(instruction) + u32 i, size = 0; + u32 return_local = fp + dest; + u32 return_value = READ_U32(return_local); + bool is_ptr = imm >> 31; + + /* reset mp to saved mp, use header size to get "real" start of frame */ + u32 frame_start = fp - FRAME_HEADER_SIZE; + u32 parent_fp = READ_U32(frame_start); + u32 return_address = READ_U32(frame_start + 4); + u32 parent_local_return_address = READ_U32(frame_start + 8); + + /* reset memory to parents end of memory */ + mp = fp - FRAME_HEADER_SIZE; + /* reset the frame pointer */ + fp = parent_fp; + + /* copy value to end of mp if it is a pointer */ + if (is_ptr) { + WRITE_U32(parent_local_return_address, mp); + size = READ_U32(return_value); + WRITE_U32(mp, size); + mp += 4; + for (i = 0; i < size; i++) { + u8 value = READ_U8(return_value + i); + WRITE_U8(mp, value); + mp++; + } + } else { + /* otherwise just write the return value to its location */ + WRITE_U32(parent_local_return_address, return_value); + } + /* jump to parent frame */ + pc = return_address; return true; } case OP_SYSCALL: { @@ -56,6 +109,42 @@ bool step_vm() { WRITE_U32(rd, (value | (((u32)(imm)) << 16))); return true; } + case OP_LOAD_IND_8: { + } + case OP_LOAD_IND_16: { + } + case OP_LOAD_IND_32: { + } + case OP_LOAD_ABS_8: { + } + case OP_LOAD_ABS_16: { + } + case OP_LOAD_ABS_32: { + } + case OP_LOAD_OFF_8: { + } + case OP_LOAD_OFF_16: { + } + case OP_LOAD_OFF_32: { + } + case OP_STORE_ABS_8: { + } + case OP_STORE_ABS_16: { + } + case OP_STORE_ABS_32: { + } + case OP_STORE_IND_8: { + } + case OP_STORE_IND_16: { + } + case OP_STORE_IND_32: { + } + case OP_STORE_OFF_8: { + } + case OP_STORE_OFF_16: { + } + case OP_STORE_OFF_32: { + } case OP_MEM_ALLOC: { DECODE_A(instruction) u32 size, ldest; @@ -86,7 +175,7 @@ bool step_vm() { return true; } - for (i = 0; i < count; i ++) { + for (i = 0; i < count; i++) { u8 value = READ_U8(mdest + i); WRITE_U8(msrc + i, value); } @@ -111,7 +200,7 @@ bool step_vm() { return true; } - for (i = 0; i < count; i ++) { + for (i = 0; i < count; i++) { u16 value = READ_U16(mdest + i); WRITE_U16(msrc + i, value); } @@ -136,7 +225,7 @@ bool step_vm() { return true; } - for (i = 0; i < count; i ++) { + for (i = 0; i < count; i++) { u32 value = READ_U32(mdest + i); WRITE_U32(msrc + i, value); } @@ -154,7 +243,7 @@ bool step_vm() { u8 value = (u8)READ_U32(r1); u32 count = READ_U32(r2); - + if (r2 == 0) { flag = 1; return true; @@ -168,7 +257,7 @@ bool step_vm() { return true; } - for (i = start; i < end; i ++) { + for (i = start; i < end; i++) { WRITE_U8(i, value); } @@ -185,7 +274,7 @@ bool step_vm() { u16 value = (u16)READ_U32(r1); u32 count = READ_U32(r2); - + if (r2 == 0) { flag = 1; return true; @@ -322,7 +411,7 @@ bool step_vm() { i32 result = (i32)READ_U32(r1) << 16; USED(src2); WRITE_U32(rd, result); - return true; + return true; } case OP_INT_TO_NAT: { DECODE_A(instruction) @@ -340,7 +429,7 @@ bool step_vm() { i32 result = ((i32)READ_U32(r1) << 16); USED(src2); WRITE_U32(rd, result); - return true; + return true; } case OP_NAT_TO_INT: { DECODE_A(instruction) @@ -404,7 +493,7 @@ bool step_vm() { USED(src2); pc = jmp_dest; - return true; + return true; } case OP_JMP_OFF: { DECODE_A(instruction) @@ -419,11 +508,11 @@ bool step_vm() { USED(src2); pc = jmp_dest; - return true; + return true; } case OP_JMP_FLAG: { DECODE_A(instruction) - u32 mask; + u32 mask; u32 rd = fp + dest; u32 jmp_dest = READ_U32(rd); if (jmp_dest > cp) { @@ -435,7 +524,7 @@ bool step_vm() { mask = -(u32)(flag == 0); pc = (jmp_dest & mask) | (pc & ~mask); - return true; + return true; } case OP_JEQ_INT: { COMPARE_AND_JUMP(i32, ==); diff --git a/vm/vm.h b/vm/vm.h index 4f09ea4..e4f0ecd 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -37,17 +37,35 @@ typedef enum { OP_HALT, /* halt : A : all zeros : halt execution */ OP_CALL, /* call : A : dest args return : creates a new frame */ - OP_RETURN, /* return : A : dest : returns from a frame to the parent frame */ + OP_RETURN, /* return : B : dest return_flags: returns from a frame to the parent frame */ OP_SYSCALL, /* syscall : A : id args mem_ptr : does a system call based on id with args */ OP_LOAD_IMM, /* load_immediate : B : locals[dest] = const as u16 */ OP_LOAD_UPPER_IMM, /* load_upper_immediate : B : locals[dest] = const as u32 << 16 | u16 */ + OP_LOAD_IND_8, /* load_indirect_8 : A : locals[dest] = memory[locals[src1]] as u8 */ + OP_LOAD_IND_16, /* load_indirect_16 : A : locals[dest] = memory[locals[src1]] as u16 */ + OP_LOAD_IND_32, /* load_indirect_32 : A : locals[dest] = memory[locals[src1]] as u32 */ + OP_LOAD_ABS_8, /* load_absolute_8 : A : locals[dest] = memory[src1] as u8 */ + OP_LOAD_ABS_16, /* load_absolute_16 : A : locals[dest] = memory[src1] as u16 */ + OP_LOAD_ABS_32, /* load_absolute_32 : A : locals[dest] = memory[src1] as u32 */ + OP_LOAD_OFF_8, /* load_offset_8 : A : locals[dest] = memory[locals[src1] + src2] as u8 */ + OP_LOAD_OFF_16, /* load_offset_16 : A : locals[dest] = memory[locals[src1] + src2] as u16 */ + OP_LOAD_OFF_32, /* load_offset_32 : A : locals[dest] = memory[locals[src1] + src2] as u32 */ + OP_STORE_ABS_8, /* store_absolute_8 : A : memory[dest] = src1 && 0xFF */ + OP_STORE_ABS_16, /* store_absolute_16 : A : memory[dest] = src1 && 0xFFFF */ + OP_STORE_ABS_32, /* store_absolute_32 : A : memory[dest] = src1 */ + OP_STORE_IND_8, /* store_indirect_8 : A : memory[dest] = locals[src1] && 0xFF */ + OP_STORE_IND_16, /* store_indirect_16 : A : memory[dest] = locals[src1] && 0xFFFF*/ + OP_STORE_IND_32, /* store_indirect_32 : A : memory[dest] = locals[src1] */ + OP_STORE_OFF_8, /* store_offset_8 : A : memory[locals[dest] + src2] = locals[src1] && 0xFF */ + OP_STORE_OFF_16, /* store_offset_16 : A : memory[locals[dest] + src2] = locals[src1] && 0xFFFF */ + OP_STORE_OFF_32, /* store_offset_32 : A : memory[locals[dest] + src2] = locals[src1] */ OP_MEM_ALLOC, /* alloc : A : memory[dest] = [locals[src1] as size + 4] */ - OP_MEM_CPY_8, /* memcpy_8 : A : memory[src1 .. src1 + count] = memory[dest .. dest + count] */ - OP_MEM_CPY_16, /* memcpy_16 : A : memory[src1 .. src1 + count] = memory[dest .. dest + count] */ - OP_MEM_CPY_32, /* memcpy_32 : A : memory[src1 .. src1 + count] = memory[dest .. dest + count] */ - OP_MEM_SET_8, /* memset_8 : A : memory[dest .. dest + count] = local[src1] as u8 */ - OP_MEM_SET_16, /* memset_16 : A : memory[dest .. dest + count] = local[src1] as u16 */ - OP_MEM_SET_32, /* memset_32 : A : memory[dest .. dest + count] = local[src1] as u32 */ + OP_MEM_CPY_8, /* memcpy_8 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */ + OP_MEM_CPY_16, /* memcpy_16 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */ + OP_MEM_CPY_32, /* memcpy_32 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */ + OP_MEM_SET_8, /* memset_8 : A : memory[dest..dest+src2] = local[src1] as u8 */ + OP_MEM_SET_16, /* memset_16 : A : memory[dest..dest+src2] = local[src1] as u16 */ + OP_MEM_SET_32, /* memset_32 : A : memory[dest..dest+src2] = local[src1] as u32 */ OP_MOV, /* mov : A : locals[dest] = locals[src1] */ OP_ADD_INT, /* add_int : A : locals[dest] = locals[src1] + locals[src2] */ OP_SUB_INT, /* sub_int : A : locals[dest] = locals[src1] - locals[src2] */ @@ -112,12 +130,6 @@ extern u8 interrupt; /* device interrupt */ extern u32 *code; /* code */ extern u8 *mem; /* memory */ -/** - * Frames - * - * - */ - #define READ_U8(addr) (mem[addr]) #define READ_U16(addr) \