#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; }