start of conditionals

This commit is contained in:
SpookyDervish
2025-12-20 16:55:40 +11:00
parent c88a6a993d
commit 7abe9c8f91
4 changed files with 124 additions and 22 deletions

BIN
fib.vmbl

Binary file not shown.

View File

@@ -9,14 +9,16 @@ VMBL_Instruction program[] = {
MAKE_INST_DUP(1), MAKE_INST_DUP(1),
MAKE_INST_DUP(1), MAKE_INST_DUP(1),
MAKE_INST_ADD, MAKE_INST_ADD,
MAKE_INST_JMP(2)
MAKE_INST_JMP(2),
}; };
int main() { int main() {
VMBL_State vmblState = {}; VMBL_State vmblState = {};
VMBL_LoadExecutable(&vmblState, program, sizeof(program)); VMBL_LoadExecutable(&vmblState, program, sizeof(program));
//VMBL_SaveExecutable("fib.vmbl", program, sizeof(program)); VMBL_SaveExecutable("fib.vmbl", program, sizeof(program));
//VMBL_LoadExecutableFromFile(&vmblState, "fib.vmbl"); VMBL_LoadExecutableFromFile(&vmblState, "fib.vmbl");
VMBL_StartVM(&vmblState); VMBL_StartVM(&vmblState);
return 0; return 0;

View File

@@ -11,7 +11,7 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i
return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW }; return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW };
} }
vmblState->stack[vmblState->stackSize++] = instruction.opperand; vmblState->stack[vmblState->stackSize++] = instruction.opperands[0];
break; break;
case INSTRUCTION_ADD: 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->stack[vmblState->stackSize - 2] += vmblState->stack[vmblState->stackSize - 1];
vmblState->stackSize--; vmblState->stackSize--;
break; 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: case INSTRUCTION_DUPLICATE:
if (vmblState->stackSize - instruction.opperand <= 0) { if (vmblState->stackSize - instruction.opperands[0] <= 0) {
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; 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 }; return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW };
} }
if (instruction.opperand < 0) { if (instruction.opperands[0] < 0) {
return (VMBL_Exception) { EXCEPTION_INVALID_OPPERAND }; 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; break;
case INSTRUCTION_JUMP: case INSTRUCTION_JUMP:
vmblState->ip = instruction.opperand; vmblState->ip = instruction.opperands[0];
break; break;
@@ -50,6 +74,44 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i
vmblState->halted = true; vmblState->halted = true;
break; 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: default:
return (VMBL_Exception) { EXCEPTION_INVALID_OPCODE }; return (VMBL_Exception) { EXCEPTION_INVALID_OPCODE };
break; break;
@@ -64,7 +126,7 @@ void VMBL_Dump(VMBL_State vmblState, VMBL_Exception exception) {
if (vmblState.stackSize > 0) { if (vmblState.stackSize > 0) {
for (size_t i = 0; i < vmblState.stackSize; i++) { 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 { } else {
fprintf(stderr, " [empty]\n"); fprintf(stderr, " [empty]\n");
@@ -83,12 +145,12 @@ void VMBL_StartVM(VMBL_State *vmblState) {
VMBL_Instruction instruction = vmblState->program[vmblState->ip++]; 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); VMBL_Exception exception = VBML_ExecuteInstruction(vmblState, instruction);
if (exception.type != EXCEPTION_NONE) { if (exception.type != EXCEPTION_NONE) {
VMBL_Dump(*vmblState, exception); //VMBL_Dump(*vmblState, exception);
return; return;
} }
@@ -108,7 +170,7 @@ void VMBL_LoadExecutable(VMBL_State *vmblState, VMBL_Instruction *program, size_
exit(1); exit(1);
} }
memcpy(vmblState->program, program, sizeof(program[0]) * programSize); memcpy(&vmblState->program, program, sizeof(program) * programSize);
vmblState->programSize = programSize; vmblState->programSize = programSize;
} }
@@ -143,7 +205,7 @@ void VMBL_SaveExecutable(const char* filePath, VMBL_Instruction *program, size_t
exit(1); exit(1);
} }
fwrite(program, sizeof(program[0]), programSize, file); fwrite(program, sizeof(program), programSize, file);
fclose(file); fclose(file);
} }
@@ -171,6 +233,18 @@ char *instructionTypeToCStr(InstructionType type) {
return "HALT"; return "HALT";
break; break;
case INSTRUCTION_EQUAL:
return "EQ ";
break;
case INSTRUCTION_EQUAL_TOP:
return "EQT ";
break;
case INSTRUCTION_JUMP_CONDITIONAL:
return "JC ";
break;
default: default:
return "??? "; return "??? ";
break; break;

View File

@@ -7,24 +7,46 @@
#include <stdbool.h> #include <stdbool.h>
#include "exception.h" #include "exception.h"
#define VMBL_STACK_SIZE 1024 #define VMBL_STACK_SIZE 0x5E
#define VMBL_PROGRAM_SIZE 1024 #define VMBL_PROGRAM_SIZE 512
typedef int64_t Word; typedef int64_t Word;
typedef enum typedef enum
{ {
// stack operations
INSTRUCTION_PUSH, INSTRUCTION_PUSH,
INSTRUCTION_ADD, INSTRUCTION_ADD,
INSTRUCTION_SUB,
INSTRUCTION_MUL,
INSTRUCTION_DIV,
INSTRUCTION_DUPLICATE, INSTRUCTION_DUPLICATE,
INSTRUCTION_POP,
// instruction pointer operations
INSTRUCTION_HALT,
INSTRUCTION_JUMP, 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; } InstructionType;
typedef struct typedef struct
{ {
InstructionType type; InstructionType type;
Word opperand; Word opperands[3];
} VMBL_Instruction; } VMBL_Instruction;
typedef struct typedef struct
@@ -39,11 +61,15 @@ typedef struct
bool halted; bool halted;
} VMBL_State; } VMBL_State;
#define MAKE_INST_PUSH(value) (VMBL_Instruction) { .type = INSTRUCTION_PUSH, .opperand = (value) } #define MAKE_INST_PUSH(value) (VMBL_Instruction) { .type = INSTRUCTION_PUSH, .opperands[0] = (value) }
#define MAKE_INST_ADD (VMBL_Instruction) { .type = INSTRUCTION_ADD, } #define MAKE_INST_POP (VMBL_Instruction) { .type = INSTRUCTION_POP, }
#define MAKE_INST_DUP(value) (VMBL_Instruction) { .type = INSTRUCTION_DUPLICATE, .opperand = (value) } #define MAKE_INST_ADD (VMBL_Instruction) { .type = INSTRUCTION_ADD }
#define MAKE_INST_JMP(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP , .opperand = (value) } #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_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); VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction);
void VMBL_Dump(VMBL_State vmblState, VMBL_Exception exception); void VMBL_Dump(VMBL_State vmblState, VMBL_Exception exception);