.
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -98,15 +98,17 @@ std::pair<std::string, size_t> 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 };
|
||||
}
|
||||
|
||||
@@ -114,14 +116,30 @@ std::pair<std::string, size_t> debug_instruction(Bytecode const& bt, uint32_t fu
|
||||
{
|
||||
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 { "???", 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -98,6 +98,9 @@ enum class Instruction : uint8_t {
|
||||
std::pair<std::string, size_t> debug_instruction(Instruction inst, int oper=0);
|
||||
std::pair<std::string, size_t> 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
|
||||
|
||||
16
src/vm/location.hh
Normal file
16
src/vm/location.hh
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef TYCHE_LOCATION_HH
|
||||
#define TYCHE_LOCATION_HH
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace tyche {
|
||||
|
||||
struct Location
|
||||
{
|
||||
uint32_t function_id;
|
||||
uint32_t pc;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //TYCHE_LOCATION_HH
|
||||
@@ -21,6 +21,8 @@ public:
|
||||
void push_fp();
|
||||
void pop_fp();
|
||||
|
||||
[[nodiscard]] size_t fp_level() const { return fps_.size(); }
|
||||
|
||||
private:
|
||||
std::vector<Value> stack_;
|
||||
std::stack<size_t> fps_;
|
||||
|
||||
12
src/vm/vm.cc
12
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
|
||||
|
||||
@@ -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_;
|
||||
|
||||
Reference in New Issue
Block a user