diff --git a/src/exception.c b/src/exception.c index 204ea87..a30d0f5 100644 --- a/src/exception.c +++ b/src/exception.c @@ -27,6 +27,10 @@ char* exceptionAsCString(VMBL_Exception exception) case EXCEPTION_INVALID_INSTRUCTION_ACCESS: return "EXCEPTION_INVALID_INSTRUCTION_ACCESS"; break; + + case EXCEPTION_DIVIDE_BY_ZERO: + return "EXCEPTION_DIVIDE_BY_ZERO"; + break; default: return "EXCEPTION_UNKOWN"; diff --git a/src/exception.h b/src/exception.h index 8b65030..3d979ec 100644 --- a/src/exception.h +++ b/src/exception.h @@ -7,7 +7,8 @@ typedef enum { EXCEPTION_STACK_UNDERFLOW, EXCEPTION_INVALID_OPCODE, EXCEPTION_INVALID_OPPERAND, - EXCEPTION_INVALID_INSTRUCTION_ACCESS + EXCEPTION_INVALID_INSTRUCTION_ACCESS, + EXCEPTION_DIVIDE_BY_ZERO } VMBL_ExceptionType; typedef struct diff --git a/src/main.c b/src/main.c index 8aadbb2..babaa1f 100644 --- a/src/main.c +++ b/src/main.c @@ -6,14 +6,13 @@ VMBL_Instruction program[] = { MAKE_INST_PUSH(123), MAKE_INST_PUSH(0), MAKE_INST_DIV, + }; int main() { VMBL_State vmblState = {}; - //VMBL_LoadExecutable(&vmblState, program, sizeof(program)); - //VMBL_SaveExecutable("fib.vmbl", program, sizeof(program)); - VMBL_LoadExecutableFromFile(&vmblState, "fib.vmbl"); + VMBL_LoadExecutable(&vmblState, program, sizeof(program)); VMBL_StartVM(&vmblState); return 0; diff --git a/src/vmbl.c b/src/vmbl.c index 3c94d54..d6753a5 100644 --- a/src/vmbl.c +++ b/src/vmbl.c @@ -3,6 +3,19 @@ #include #include + +#define MATH_OP(vmblState, operation) \ + do { \ + if ((vmblState)->stackSize < 2) { \ + return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; \ + } \ + (vmblState)->stack[(vmblState)->stackSize - 2] = (vmblState)->stack[(vmblState)->stackSize - 2] operation (vmblState)->stack[(vmblState)->stackSize - 1]; \ + (vmblState)->stackSize--; \ + (vmblState)->ip++; \ + } while (0); + + + VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction) { switch (instruction.type) { @@ -15,36 +28,20 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i break; case INSTRUCTION_ADD: - if (vmblState->stackSize < 2) { - return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; - } - - vmblState->stack[vmblState->stackSize - 2] += vmblState->stack[vmblState->stackSize - 1]; - vmblState->stackSize--; + MATH_OP(vmblState, +); break; case INSTRUCTION_SUB: - if (vmblState->stackSize < 2) { - return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; - } - - vmblState->stack[vmblState->stackSize - 2] -= vmblState->stack[vmblState->stackSize - 1]; - vmblState->stackSize--; + MATH_OP(vmblState, -); break; case INSTRUCTION_MUL: - if (vmblState->stackSize < 2) { - return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; - } - - vmblState->stack[vmblState->stackSize - 2] *= vmblState->stack[vmblState->stackSize - 1]; - vmblState->stackSize--; + MATH_OP(vmblState, *); break; case INSTRUCTION_DIV: - if (vmblState->stackSize < 2) { - return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; - } + if (instruction.opperands[0] == 0) { + return (VMBL_Exception){ EXCEPTION_DIVIDE_BY_ZERO }; + } - vmblState->stack[vmblState->stackSize - 2] /= vmblState->stack[vmblState->stackSize - 1]; - vmblState->stackSize--; + MATH_OP(vmblState, /); break; case INSTRUCTION_DUPLICATE: @@ -75,22 +72,7 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i break; case INSTRUCTION_EQUAL: - if (instruction.opperands[0] < 0 || instruction.opperands[1] < 0) { - return (VMBL_Exception) { EXCEPTION_INVALID_OPPERAND }; - } - if (vmblState->stackSize >= VMBL_STACK_SIZE || instruction.opperands[0] > VMBL_STACK_SIZE || instruction.opperands[1] > VMBL_STACK_SIZE) { - return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW }; - } - - vmblState->stack[vmblState->stackSize] = vmblState->stack[vmblState->stackSize-instruction.opperands[0]] == vmblState->stack[vmblState->stackSize-instruction.opperands[1]]; - break; - - case INSTRUCTION_EQUAL_TOP: - if (vmblState->stackSize >= VMBL_STACK_SIZE) { - return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW }; - } - - vmblState->stack[vmblState->stackSize++] = vmblState->stack[vmblState->stackSize-1] == vmblState->stack[vmblState->stackSize-2]; + MATH_OP(vmblState, ==); break; case INSTRUCTION_JUMP_CONDITIONAL: @@ -103,7 +85,7 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i } break; - case INSTRUCTION_POP: + case INSTRUCTION_DROP: if (vmblState->stackSize <= 0) { return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; } @@ -145,12 +127,12 @@ void VMBL_StartVM(VMBL_State *vmblState) { VMBL_Instruction instruction = vmblState->program[vmblState->ip++]; - //printf("%s 0x%lx, 0x%lx, 0x%lx\n", instructionTypeToCStr(instruction.type), instruction.opperands[0], instruction.opperands[1], instruction.opperands[2]); + printf("%s 0x%lx, 0x%lx, 0x%lx\n", instructionTypeToCStr(instruction.type), instruction.opperands[0], instruction.opperands[1], instruction.opperands[2]); VMBL_Exception exception = VBML_ExecuteInstruction(vmblState, instruction); if (exception.type != EXCEPTION_NONE) { - //VMBL_Dump(*vmblState, exception); + VMBL_Dump(*vmblState, exception); return; } @@ -220,6 +202,15 @@ char *instructionTypeToCStr(InstructionType type) { case INSTRUCTION_ADD: return "ADD "; break; + case INSTRUCTION_SUB: + return "SUB "; + break; + case INSTRUCTION_MUL: + return "MUL "; + break; + case INSTRUCTION_DIV: + return "DIV "; + break; case INSTRUCTION_DUPLICATE: return "DUP "; @@ -237,10 +228,6 @@ char *instructionTypeToCStr(InstructionType type) { return "EQ "; break; - case INSTRUCTION_EQUAL_TOP: - return "EQT "; - break; - case INSTRUCTION_JUMP_CONDITIONAL: return "JC "; break; diff --git a/src/vmbl.h b/src/vmbl.h index 24e869f..a7d489a 100644 --- a/src/vmbl.h +++ b/src/vmbl.h @@ -21,7 +21,7 @@ typedef enum INSTRUCTION_MUL, INSTRUCTION_DIV, INSTRUCTION_DUPLICATE, - INSTRUCTION_POP, + INSTRUCTION_DROP, // instruction pointer operations INSTRUCTION_HALT, @@ -30,17 +30,11 @@ typedef enum // conditional operations INSTRUCTION_NOT_EQUAL, - INSTRUCTION_NOT_EQUAL_TOP, INSTRUCTION_EQUAL, - INSTRUCTION_EQUAL_TOP, INSTRUCTION_LESS_THAN, - INSTRUCTION_LESS_THAN_TOP, INSTRUCTION_LESS_THAN_EQUAL, - INSTRUCTION_LESS_THAN_EQUAL_TOP, INSTRUCTION_GREATER_THAN, - INSTRUCTION_GREATER_THAN_TOP, INSTRUCTION_GREATER_THAN_EQUAL, - INSTRUCTION_GREATER_THAN_EQUAL_TOP, } InstructionType; typedef struct @@ -62,7 +56,7 @@ typedef struct } VMBL_State; #define MAKE_INST_PUSH(value) (VMBL_Instruction) { .type = INSTRUCTION_PUSH, .opperands[0] = (value) } -#define MAKE_INST_POP (VMBL_Instruction) { .type = INSTRUCTION_POP } +#define MAKE_INST_DROP (VMBL_Instruction) { .type = INSTRUCTION_POP } #define MAKE_INST_ADD (VMBL_Instruction) { .type = INSTRUCTION_ADD } #define MAKE_INST_SUB (VMBL_Instruction) { .type = INSTRUCTION_SUB } #define MAKE_INST_MUL (VMBL_Instruction) { .type = INSTRUCTION_MUL } @@ -70,8 +64,12 @@ typedef struct #define MAKE_INST_DUP(value) (VMBL_Instruction) { .type = INSTRUCTION_DUPLICATE, .opperands[0] = (value) } #define MAKE_INST_JMP(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP, .opperands[0] = (value) } #define MAKE_INST_HALT (VMBL_Instruction) { .type = INSTRUCTION_HALT } -#define MAKE_INST_EQUAL(stack1, stack2) (VMBL_Instruction) { .type = INSTRUCTION_EQUAL, .opperands[0] = (stack1), .opperands[1] = (stack2) } -#define MAKE_INST_EQUAL_TOP (VMBL_Instruction) { .type = INSTRUCTION_EQUAL_TOP } +#define MAKE_INST_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_EQUAL } +#define MAKE_INST_NOT_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_NOT_EQUAL } +#define MAKE_INST_LESS (VMBL_Instruction) { .type = INSTRUCTION_LESS_THAN } +#define MAKE_INST_LESS_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_LESS_THAN_EQUAL } +#define MAKE_INST_GREATER (VMBL_Instruction) { .type = INSTRUCTION_GREATER_THAN } +#define MAKE_INST_GREATER_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_GREATER_THAN_EQUAL } #define MAKE_INST_JUMP_CONDITIONAL(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP_CONDITIONAL, .opperands[0] = (value) } VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction);