diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b89896..d43741d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,8 @@ target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings}) # tests # -add_executable(${PROJECT_NAME}-bytecode-test src/bytecode/tests.cc) +add_executable(${PROJECT_NAME}-bytecode-test src/bytecode/tests.cc + src/vm/location.hh) target_link_libraries(${PROJECT_NAME}-bytecode-test lib${PROJECT_NAME} gtest_main) add_test(NAME tyche_bytecode_test COMMAND ${PROJECT_NAME}-bytecode-test) diff --git a/src/vm/code.cc b/src/vm/code.cc index 450963c..1f2cb81 100644 --- a/src/vm/code.cc +++ b/src/vm/code.cc @@ -14,6 +14,41 @@ FunctionId Code::import_bytecode(ByteArray incoming) return 0; // TODO } +Operation Code::operation(Location const& location) const +{ + Instruction inst = (Instruction) bytecode_.get_code_byte(location.function_id, location.pc); + OperandType opet = instruction_operand_type(inst); + + switch (opet) { + case OperandType::NoOperand: + return { + .instruction = inst, + .operator_ = 0, + .next_location = { .function_id = location.function_id, .pc = location.pc + 1 }, + }; + case OperandType::Int8: + return { + .instruction = inst, + .operator_ = bytecode_.get_code_int8(location.function_id, location.pc + 1), + .next_location = { .function_id = location.function_id, .pc = location.pc + 2 }, + }; + case OperandType::Int16: + return { + .instruction = inst, + .operator_ = bytecode_.get_code_int16(location.function_id, location.pc + 1), + .next_location = { .function_id = location.function_id, .pc = location.pc + 3 }, + }; + case OperandType::Int32: + return { + .instruction = inst, + .operator_ = bytecode_.get_code_int32(location.function_id, location.pc + 1), + .next_location = { .function_id = location.function_id, .pc = location.pc + 5 }, + }; + } + + throw std::logic_error("Should not get here"); +} + std::string Code::disassemble() const { std::string out; diff --git a/src/vm/code.hh b/src/vm/code.hh index 2925be3..19084b6 100644 --- a/src/vm/code.hh +++ b/src/vm/code.hh @@ -1,17 +1,28 @@ #ifndef TYCHE_CODE_HH #define TYCHE_CODE_HH +#include "instruction.hh" +#include "location.hh" #include "value.hh" #include "../bytecode/bytecode.hh" namespace tyche { +struct Operation +{ + Instruction instruction; + int32_t operator_; + Location next_location; +}; + class Code { public: FunctionId import_bytecode(ByteArray incoming); [[nodiscard]] std::string disassemble() const; + [[nodiscard]] Operation operation(Location const& location) const; + private: Bytecode bytecode_; }; diff --git a/src/vm/instruction.cc b/src/vm/instruction.cc index 50077a5..d83a8c5 100644 --- a/src/vm/instruction.cc +++ b/src/vm/instruction.cc @@ -98,30 +98,48 @@ std::pair debug_instruction(Instruction inst, int oper) out = "???"; } - if ((uint8_t) inst < 0xa0) + OperandType operands = instruction_operand_type(inst); + + if (operands == OperandType::NoOperand) return { out, 1 }; out += " " + std::to_string(oper); - if ((uint8_t) inst >= 0xe0) + if (operands == OperandType::Int32) return { out, 5 }; - else if ((uint8_t) inst >= 0xc0) + if (operands == OperandType::Int16) return { out, 3 }; - else - return { out, 2 }; + + return { out, 2 }; } std::pair debug_instruction(Bytecode const& bt, uint32_t function_id, uint32_t addr) { auto inst = (Instruction) bt.get_code_byte(function_id, addr); - if ((uint8_t) inst >= 0xe0) - return debug_instruction(inst, bt.get_code_int32(function_id, addr + 1)); - else if ((uint8_t) inst >= 0xc0) - return debug_instruction(inst, bt.get_code_int16(function_id, addr + 1)); - else if ((uint8_t) inst >= 0xa0) - return debug_instruction(inst, bt.get_code_int8(function_id, addr + 1)); + switch (instruction_operand_type(inst)) { + case OperandType::NoOperand: + return debug_instruction(inst); + case OperandType::Int8: + return debug_instruction(inst, bt.get_code_int8(function_id, addr + 1)); + case OperandType::Int16: + return debug_instruction(inst, bt.get_code_int16(function_id, addr + 1)); + case OperandType::Int32: + return debug_instruction(inst, bt.get_code_int32(function_id, addr + 1)); + default: + } - return debug_instruction(inst); + return { "???", 1 }; +} + +OperandType instruction_operand_type(Instruction inst) +{ + if ((uint8_t) inst >= 0xe0) + return OperandType::Int32; + if ((uint8_t) inst >= 0xc0) + return OperandType::Int16; + if ((uint8_t) inst >= 0xa0) + return OperandType::Int8; + return OperandType::NoOperand; } } \ No newline at end of file diff --git a/src/vm/instruction.hh b/src/vm/instruction.hh index 0cb9959..1bbc202 100644 --- a/src/vm/instruction.hh +++ b/src/vm/instruction.hh @@ -98,6 +98,9 @@ enum class Instruction : uint8_t { std::pair debug_instruction(Instruction inst, int oper=0); std::pair debug_instruction(Bytecode const& bt, uint32_t function_id, uint32_t addr); +enum class OperandType { NoOperand, Int8, Int16, Int32 }; +OperandType instruction_operand_type(Instruction instruction); + } #endif //TYCHE_INSTRUCTION_HH diff --git a/src/vm/location.hh b/src/vm/location.hh new file mode 100644 index 0000000..9e67c76 --- /dev/null +++ b/src/vm/location.hh @@ -0,0 +1,16 @@ +#ifndef TYCHE_LOCATION_HH +#define TYCHE_LOCATION_HH + +#include + +namespace tyche { + +struct Location +{ + uint32_t function_id; + uint32_t pc; +}; + +} + +#endif //TYCHE_LOCATION_HH diff --git a/src/vm/stack.hh b/src/vm/stack.hh index c6b59ac..f42990b 100644 --- a/src/vm/stack.hh +++ b/src/vm/stack.hh @@ -21,6 +21,8 @@ public: void push_fp(); void pop_fp(); + [[nodiscard]] size_t fp_level() const { return fps_.size(); } + private: std::vector stack_; std::stack fps_; diff --git a/src/vm/vm.cc b/src/vm/vm.cc index 705f49d..4874fd5 100644 --- a/src/vm/vm.cc +++ b/src/vm/vm.cc @@ -27,7 +27,19 @@ void VM::call(size_t n_params) void VM::run_until_return() { + size_t level = stack_.fp_level(); + while (stack_.fp_level() >= level) + step(); +} + +void VM::step() +{ + Operation op = code_.operation(loc_.top()); + switch (op.instruction) { + // TODO + } + loc_.top() = op.next_location; } } // tyche diff --git a/src/vm/vm.hh b/src/vm/vm.hh index 852b583..76f49b9 100644 --- a/src/vm/vm.hh +++ b/src/vm/vm.hh @@ -2,6 +2,7 @@ #define TYCHE_VM_HH #include "code.hh" +#include "location.hh" #include "stack.hh" namespace tyche { @@ -13,9 +14,8 @@ public: void call(size_t n_params); private: - struct Location { uint32_t function_id; uint32_t pc; }; - void run_until_return(); + void step(); Stack stack_; Code code_;