diff --git a/fib.vmbl b/fib.vmbl index ec10039..d8dfbeb 100644 Binary files a/fib.vmbl and b/fib.vmbl differ diff --git a/src/main.c b/src/main.c index df6e216..ad3c2e8 100644 --- a/src/main.c +++ b/src/main.c @@ -9,14 +9,16 @@ VMBL_Instruction program[] = { MAKE_INST_DUP(1), MAKE_INST_DUP(1), MAKE_INST_ADD, - MAKE_INST_JMP(2) + + MAKE_INST_JMP(2), }; int main() { VMBL_State vmblState = {}; + VMBL_LoadExecutable(&vmblState, program, sizeof(program)); - //VMBL_SaveExecutable("fib.vmbl", program, sizeof(program)); - //VMBL_LoadExecutableFromFile(&vmblState, "fib.vmbl"); + VMBL_SaveExecutable("fib.vmbl", program, sizeof(program)); + VMBL_LoadExecutableFromFile(&vmblState, "fib.vmbl"); VMBL_StartVM(&vmblState); return 0; diff --git a/src/vmbl.c b/src/vmbl.c index e048cb1..3c94d54 100644 --- a/src/vmbl.c +++ b/src/vmbl.c @@ -11,7 +11,7 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW }; } - vmblState->stack[vmblState->stackSize++] = instruction.opperand; + vmblState->stack[vmblState->stackSize++] = instruction.opperands[0]; break; case INSTRUCTION_ADD: @@ -22,9 +22,33 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i vmblState->stack[vmblState->stackSize - 2] += vmblState->stack[vmblState->stackSize - 1]; vmblState->stackSize--; 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--; + 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--; + break; + case INSTRUCTION_DIV: + if (vmblState->stackSize < 2) { + return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; + } + + vmblState->stack[vmblState->stackSize - 2] /= vmblState->stack[vmblState->stackSize - 1]; + vmblState->stackSize--; + break; case INSTRUCTION_DUPLICATE: - if (vmblState->stackSize - instruction.opperand <= 0) { + if (vmblState->stackSize - instruction.opperands[0] <= 0) { return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; } @@ -32,17 +56,17 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW }; } - if (instruction.opperand < 0) { + if (instruction.opperands[0] < 0) { return (VMBL_Exception) { EXCEPTION_INVALID_OPPERAND }; } - vmblState->stack[vmblState->stackSize++] = vmblState->stack[vmblState->stackSize - 1 - instruction.opperand]; + vmblState->stack[vmblState->stackSize++] = vmblState->stack[vmblState->stackSize - 1 - instruction.opperands[0]]; break; case INSTRUCTION_JUMP: - vmblState->ip = instruction.opperand; + vmblState->ip = instruction.opperands[0]; break; @@ -50,6 +74,44 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i vmblState->halted = true; 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]; + break; + + case INSTRUCTION_JUMP_CONDITIONAL: + if (instruction.opperands[0] < 0) { + return (VMBL_Exception) { EXCEPTION_INVALID_OPPERAND }; + } + + if (vmblState->stack[vmblState->stackSize--]) { + vmblState->ip = instruction.opperands[0]; + } + break; + + case INSTRUCTION_POP: + if (vmblState->stackSize <= 0) { + return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; + } + + vmblState->stackSize--; + + break; + default: return (VMBL_Exception) { EXCEPTION_INVALID_OPCODE }; break; @@ -64,7 +126,7 @@ void VMBL_Dump(VMBL_State vmblState, VMBL_Exception exception) { if (vmblState.stackSize > 0) { for (size_t i = 0; i < vmblState.stackSize; i++) { - fprintf(stderr, " 0x%lX: 0x%ld\n", i, vmblState.stack[i]); + fprintf(stderr, " 0x%lX: %ld\n", i, vmblState.stack[i]); } } else { fprintf(stderr, " [empty]\n"); @@ -83,12 +145,12 @@ void VMBL_StartVM(VMBL_State *vmblState) { VMBL_Instruction instruction = vmblState->program[vmblState->ip++]; - printf("%s 0x%lx\n", instructionTypeToCStr(instruction.type), instruction.opperand); + //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; } @@ -108,7 +170,7 @@ void VMBL_LoadExecutable(VMBL_State *vmblState, VMBL_Instruction *program, size_ exit(1); } - memcpy(vmblState->program, program, sizeof(program[0]) * programSize); + memcpy(&vmblState->program, program, sizeof(program) * programSize); vmblState->programSize = programSize; } @@ -143,7 +205,7 @@ void VMBL_SaveExecutable(const char* filePath, VMBL_Instruction *program, size_t exit(1); } - fwrite(program, sizeof(program[0]), programSize, file); + fwrite(program, sizeof(program), programSize, file); fclose(file); } @@ -170,6 +232,18 @@ char *instructionTypeToCStr(InstructionType type) { case INSTRUCTION_HALT: return "HALT"; break; + + case INSTRUCTION_EQUAL: + return "EQ "; + break; + + case INSTRUCTION_EQUAL_TOP: + return "EQT "; + break; + + case INSTRUCTION_JUMP_CONDITIONAL: + return "JC "; + break; default: return "??? "; diff --git a/src/vmbl.h b/src/vmbl.h index 5b337c1..333e57e 100644 --- a/src/vmbl.h +++ b/src/vmbl.h @@ -7,24 +7,46 @@ #include #include "exception.h" -#define VMBL_STACK_SIZE 1024 -#define VMBL_PROGRAM_SIZE 1024 +#define VMBL_STACK_SIZE 0x5E +#define VMBL_PROGRAM_SIZE 512 typedef int64_t Word; typedef enum { + // stack operations INSTRUCTION_PUSH, INSTRUCTION_ADD, + INSTRUCTION_SUB, + INSTRUCTION_MUL, + INSTRUCTION_DIV, INSTRUCTION_DUPLICATE, + INSTRUCTION_POP, + + // instruction pointer operations + INSTRUCTION_HALT, INSTRUCTION_JUMP, - INSTRUCTION_HALT + INSTRUCTION_JUMP_CONDITIONAL, + + // 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 { InstructionType type; - Word opperand; + Word opperands[3]; } VMBL_Instruction; typedef struct @@ -39,11 +61,15 @@ typedef struct bool halted; } VMBL_State; -#define MAKE_INST_PUSH(value) (VMBL_Instruction) { .type = INSTRUCTION_PUSH, .opperand = (value) } -#define MAKE_INST_ADD (VMBL_Instruction) { .type = INSTRUCTION_ADD, } -#define MAKE_INST_DUP(value) (VMBL_Instruction) { .type = INSTRUCTION_DUPLICATE, .opperand = (value) } -#define MAKE_INST_JMP(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP , .opperand = (value) } -#define MAKE_INST_HALT (VMBL_Instruction) { .type = INSTRUCTION_HALT } +#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_ADD (VMBL_Instruction) { .type = INSTRUCTION_ADD } +#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_JUMP_CONDITIONAL(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP_CONDITIONAL, .opperands[0] = (value) } VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction); void VMBL_Dump(VMBL_State vmblState, VMBL_Exception exception);