undar-lang/vm/vm.c

294 lines
5.4 KiB
C

#include "vm.h"
u32 pc; /* program counter */
u32 cp; /* code pointer */
u32 mp; /* memory pointer */
u32 fp; /* frame pointer */
u32 flag; /* flag */
u8 interrupt; /* device interrupt */
u32 *code; /* code */
u8 *mem; /* memory */
bool step_vm() {
u32 instruction = code[pc];
u8 opcode = DECODE_OP(instruction);
switch (opcode) {
case OP_HALT: {
/* no need to decode, all are zeros */
return false;
}
case OP_CALL: {
}
case OP_RETURN: {
}
case OP_SYSCALL: {
DECODE_A(instruction)
u32 id = fp + dest;
u32 args = fp + src1;
u32 mem_ptr = fp + src2;
flag = syscall(id, args, mem_ptr);
return true;
}
case OP_LOAD_IMM: {
DECODE_B(instruction)
u32 rd = fp + dest;
mem[rd] = imm;
return true;
}
case OP_LOAD_UPPER_IMM: {
DECODE_B(instruction)
u32 rd = fp + dest;
mem[rd] = (mem[rd] | (((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: {
}
case OP_MEM_CPY: {
}
case OP_MEM_SET_8: {
}
case OP_MEM_SET_16: {
}
case OP_MEM_SET_32: {
}
case OP_REG_MOV: {
}
case OP_ADD_INT: {
MATH_OP(i32, +);
}
case OP_SUB_INT: {
MATH_OP(i32, -);
}
case OP_MUL_INT: {
MATH_OP(i32, *);
}
case OP_DIV_INT: {
MATH_OP(i32, /);
}
case OP_ADD_NAT: {
MATH_OP(u32, +);
}
case OP_SUB_NAT: {
MATH_OP(u32, -);
}
case OP_MUL_NAT: {
MATH_OP(u32, *);
}
case OP_DIV_NAT: {
MATH_OP(u32, /);
}
case OP_ADD_REAL: {
MATH_OP(i32, +);
}
case OP_SUB_REAL: {
MATH_OP(i32, -);
}
case OP_MUL_REAL: {
DECODE_A(instruction)
u32 rd = fp + dest;
u32 r1 = fp + src1;
u32 r2 = fp + src2;
i32 src1_whole = (i32)mem[r1] >> 16;
i32 src2_whole = (i32)mem[r2] >> 16;
i32 src1_decimal = (i32)mem[r1] & 16;
i32 src2_decimal = (i32)mem[r2] & 16;
i32 result = 0;
result += (src1_whole * src2_whole) << 16;
result += (src1_whole * src2_decimal);
result += (src1_decimal * src2_whole);
result += ((src1_decimal * src2_decimal) >> 16) & 16;
mem[rd] = result;
return true;
}
case OP_DIV_REAL: {
DECODE_A(instruction)
i32 result;
u32 rd = fp + dest;
u32 r1 = fp + src1;
u32 r2 = fp + src2;
i32 src1_val = (i32)mem[r1];
i32 src2_val = (i32)mem[r2];
u32 src2_reciprocal = 1;
src2_reciprocal <<= 31;
src2_reciprocal = (u32)(src2_reciprocal / src2_val);
result = src1_val * src2_reciprocal;
result <<= 1;
mem[rd] = result;
return true;
}
case OP_INT_TO_REAL: {
DECODE_A(instruction)
u32 rd = fp + dest;
u32 r1 = fp + src1;
USED(src2);
mem[rd] = (i32)mem[r1] << 16;
return true;
}
case OP_INT_TO_NAT: {
DECODE_A(instruction)
u32 rd = fp + dest;
u32 r1 = fp + src1;
USED(src2);
mem[rd] = (u32)mem[r1];
return true;
}
case OP_NAT_TO_REAL: {
DECODE_A(instruction)
u32 rd = fp + dest;
u32 r1 = fp + src1;
USED(src2);
mem[rd] = (i32)mem[r1] << 16;
return true;
}
case OP_NAT_TO_INT: {
DECODE_A(instruction)
u32 rd = fp + dest;
u32 r1 = fp + src1;
USED(src2);
mem[rd] = (i32)mem[r1];
return true;
}
case OP_REAL_TO_INT: {
DECODE_A(instruction)
u32 rd = fp + dest;
u32 r1 = fp + src1;
USED(src2);
mem[rd] = (i32)mem[r1] >> 16;
return true;
}
case OP_REAL_TO_NAT: {
DECODE_A(instruction)
u32 rd = fp + dest;
u32 r1 = fp + src1;
USED(src2);
mem[rd] = (u32)mem[r1] >> 16;
return true;
}
case OP_BIT_SHIFT_LEFT: {
}
case OP_BIT_SHIFT_RIGHT: {
}
case OP_BIT_SHIFT_R_EXT: {
}
case OP_BIT_AND: {
}
case OP_BIT_OR: {
}
case OP_BIT_XOR: {
}
case OP_JMP_IMM: {
DECODE_C(instruction)
pc = imm;
return true;
}
case OP_JMP_ABS: {
}
case OP_JMP_OFF: {
}
case OP_JMP_FLAG: {
}
case OP_JEQ_INT: {
COMPARE_AND_JUMP(i32, ==);
}
case OP_JNE_INT: {
COMPARE_AND_JUMP(i32, !=);
}
case OP_JGT_INT: {
COMPARE_AND_JUMP(i32, >);
}
case OP_JLT_INT: {
COMPARE_AND_JUMP(i32, <);
}
case OP_JLE_INT: {
COMPARE_AND_JUMP(i32, <=);
}
case OP_JGE_INT: {
COMPARE_AND_JUMP(i32, >=);
}
case OP_JEQ_NAT: {
COMPARE_AND_JUMP(u32, ==);
}
case OP_JNE_NAT: {
COMPARE_AND_JUMP(u32, !=);
}
case OP_JGT_NAT: {
COMPARE_AND_JUMP(u32, >);
}
case OP_JLT_NAT: {
COMPARE_AND_JUMP(u32, <);
}
case OP_JLE_NAT: {
COMPARE_AND_JUMP(u32, <=);
}
case OP_JGE_NAT: {
COMPARE_AND_JUMP(u32, >=);
}
case OP_JEQ_REAL: {
COMPARE_AND_JUMP(i32, ==);
}
case OP_JNE_REAL: {
COMPARE_AND_JUMP(i32, !=);
}
case OP_JGE_REAL: {
COMPARE_AND_JUMP(i32, >=);
}
case OP_JGT_REAL: {
COMPARE_AND_JUMP(i32, >);
}
case OP_JLT_REAL: {
COMPARE_AND_JUMP(i32, <);
}
case OP_JLE_REAL: {
COMPARE_AND_JUMP(i32, <=);
}
}
/* something went very wrong */
flag = 255;
return false;
}