WIP: implement call and return instructions
This commit is contained in:
parent
34b6fa96ca
commit
4635c83e42
101
vm/vm.c
101
vm/vm.c
|
|
@ -1,5 +1,7 @@
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
|
#define FRAME_HEADER_SIZE 12
|
||||||
|
|
||||||
u32 pc; /* program counter */
|
u32 pc; /* program counter */
|
||||||
u32 cp; /* code pointer */
|
u32 cp; /* code pointer */
|
||||||
u32 mp; /* memory pointer */
|
u32 mp; /* memory pointer */
|
||||||
|
|
@ -20,19 +22,70 @@ bool step_vm() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case OP_CALL: {
|
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 */
|
/* push return address to child frame */
|
||||||
|
WRITE_U32(mp, pc + 1);
|
||||||
|
mp += 4;
|
||||||
/* push local address to return the value to */
|
/* push local address to return the value to */
|
||||||
/* push current mp value to reset the heap to */
|
WRITE_U32(mp, return_ptr);
|
||||||
/* move mp by args many locals */
|
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 */
|
/* jump to dest_ptr */
|
||||||
|
pc = fn_ptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_RETURN: {
|
case OP_RETURN: {
|
||||||
/* DECODE_A(instruction) */
|
DECODE_B(instruction)
|
||||||
/* copy return value to parent return local */
|
u32 i, size = 0;
|
||||||
/* reset mp to saved mp */
|
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 */
|
/* jump to parent frame */
|
||||||
|
pc = return_address;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_SYSCALL: {
|
case OP_SYSCALL: {
|
||||||
|
|
@ -56,6 +109,42 @@ bool step_vm() {
|
||||||
WRITE_U32(rd, (value | (((u32)(imm)) << 16)));
|
WRITE_U32(rd, (value | (((u32)(imm)) << 16)));
|
||||||
return true;
|
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: {
|
case OP_MEM_ALLOC: {
|
||||||
DECODE_A(instruction)
|
DECODE_A(instruction)
|
||||||
u32 size, ldest;
|
u32 size, ldest;
|
||||||
|
|
|
||||||
38
vm/vm.h
38
vm/vm.h
|
|
@ -37,17 +37,35 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OP_HALT, /* halt : A : all zeros : halt execution */
|
OP_HALT, /* halt : A : all zeros : halt execution */
|
||||||
OP_CALL, /* call : A : dest args return : creates a new frame */
|
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_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_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_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_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_8, /* memcpy_8 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */
|
||||||
OP_MEM_CPY_16, /* memcpy_16 : A : memory[src1 .. src1 + count] = memory[dest .. dest + count] */
|
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 + count] = memory[dest .. dest + count] */
|
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 + count] = local[src1] as u8 */
|
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 + count] = local[src1] as u16 */
|
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 + count] = local[src1] as u32 */
|
OP_MEM_SET_32, /* memset_32 : A : memory[dest..dest+src2] = local[src1] as u32 */
|
||||||
OP_MOV, /* mov : A : locals[dest] = locals[src1] */
|
OP_MOV, /* mov : A : locals[dest] = locals[src1] */
|
||||||
OP_ADD_INT, /* add_int : A : locals[dest] = locals[src1] + locals[src2] */
|
OP_ADD_INT, /* add_int : A : locals[dest] = locals[src1] + locals[src2] */
|
||||||
OP_SUB_INT, /* sub_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 u32 *code; /* code */
|
||||||
extern u8 *mem; /* memory */
|
extern u8 *mem; /* memory */
|
||||||
|
|
||||||
/**
|
|
||||||
* Frames
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define READ_U8(addr) (mem[addr])
|
#define READ_U8(addr) (mem[addr])
|
||||||
|
|
||||||
#define READ_U16(addr) \
|
#define READ_U16(addr) \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue