feat(furvm): improve instruction abstraction
Add reading and writing to instruction abstraction.
This commit is contained in:
@@ -3,19 +3,26 @@
|
|||||||
|
|
||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
namespace furvm {
|
namespace furvm {
|
||||||
|
|
||||||
struct instruction_argument {
|
struct instruction_argument {
|
||||||
enum type_e {
|
enum type_e {
|
||||||
None = 0,
|
None = 0,
|
||||||
Byte,
|
S8,
|
||||||
Short,
|
U8,
|
||||||
Int,
|
S16,
|
||||||
|
U16,
|
||||||
|
S32,
|
||||||
|
U32,
|
||||||
Constant,
|
Constant,
|
||||||
Type,
|
Type,
|
||||||
Variable,
|
Variable,
|
||||||
Function,
|
Function,
|
||||||
Offset,
|
Offset,
|
||||||
|
|
||||||
|
Count,
|
||||||
} type;
|
} type;
|
||||||
union {
|
union {
|
||||||
std::int8_t s8;
|
std::int8_t s8;
|
||||||
@@ -25,6 +32,12 @@ struct instruction_argument {
|
|||||||
std::int32_t s32;
|
std::int32_t s32;
|
||||||
std::uint32_t u32;
|
std::uint32_t u32;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const std::size_t s_sizes[Count];
|
||||||
|
static const bool s_signedness[Count];
|
||||||
|
|
||||||
|
std::size_t size() const { return s_sizes[type]; }
|
||||||
|
bool is_signed() const { return s_signedness[type]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
using instruction_argument_t = instruction_argument::type_e;
|
using instruction_argument_t = instruction_argument::type_e;
|
||||||
@@ -72,7 +85,10 @@ struct instruction {
|
|||||||
} type;
|
} type;
|
||||||
instruction_argument arg;
|
instruction_argument arg;
|
||||||
|
|
||||||
static instruction_argument_t s_arguments[Count];
|
static const instruction_argument_t s_arguments[Count];
|
||||||
|
|
||||||
|
std::size_t read(std::string_view in);
|
||||||
|
std::size_t write(std::string& out) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
using instruction_t = instruction::type_e;
|
using instruction_t = instruction::type_e;
|
||||||
|
|||||||
@@ -1,22 +1,79 @@
|
|||||||
#include "furvm/instruction.hpp"
|
#include "furvm/instruction.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace furvm {
|
namespace furvm {
|
||||||
|
|
||||||
instruction_argument_t instruction::s_arguments[instruction::Count] = {
|
const std::size_t instruction_argument::s_sizes[instruction_argument::Count] = {
|
||||||
|
// None:
|
||||||
|
0,
|
||||||
|
// S8:
|
||||||
|
1,
|
||||||
|
// U8:
|
||||||
|
1,
|
||||||
|
// S16:
|
||||||
|
2,
|
||||||
|
// U16:
|
||||||
|
2,
|
||||||
|
// S32
|
||||||
|
4,
|
||||||
|
// U32
|
||||||
|
4,
|
||||||
|
// Constant:
|
||||||
|
4,
|
||||||
|
// Type:
|
||||||
|
4,
|
||||||
|
// Variable:
|
||||||
|
2,
|
||||||
|
// Function:
|
||||||
|
4,
|
||||||
|
// Offset:
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool instruction_argument::s_signedness[instruction_argument::Count] = {
|
||||||
|
// None:
|
||||||
|
false,
|
||||||
|
// S8:
|
||||||
|
true,
|
||||||
|
// U8:
|
||||||
|
false,
|
||||||
|
// S16:
|
||||||
|
true,
|
||||||
|
// U16:
|
||||||
|
false,
|
||||||
|
// S32
|
||||||
|
true,
|
||||||
|
// U32:
|
||||||
|
false,
|
||||||
|
// Constant:
|
||||||
|
false,
|
||||||
|
// Type:
|
||||||
|
false,
|
||||||
|
// Variable:
|
||||||
|
false,
|
||||||
|
// Function:
|
||||||
|
false,
|
||||||
|
// Offset:
|
||||||
|
true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const instruction_argument_t instruction::s_arguments[instruction::Count] = {
|
||||||
// NoOperation:
|
// NoOperation:
|
||||||
instruction_argument::None,
|
instruction_argument::None,
|
||||||
// PushS8:
|
// PushS8:
|
||||||
instruction_argument::Byte,
|
instruction_argument::S8,
|
||||||
// PushU8:
|
// PushU8:
|
||||||
instruction_argument::Byte,
|
instruction_argument::U8,
|
||||||
// PushS16:
|
// PushS16:
|
||||||
instruction_argument::Short,
|
instruction_argument::S16,
|
||||||
// PushU16:
|
// PushU16:
|
||||||
instruction_argument::Short,
|
instruction_argument::U16,
|
||||||
// PushS32:
|
// PushS32:
|
||||||
instruction_argument::Int,
|
instruction_argument::S32,
|
||||||
// PushU32:
|
// PushU32:
|
||||||
instruction_argument::Int,
|
instruction_argument::U32,
|
||||||
// PushConstant:
|
// PushConstant:
|
||||||
instruction_argument::Constant,
|
instruction_argument::Constant,
|
||||||
// Array:
|
// Array:
|
||||||
@@ -77,4 +134,33 @@ instruction_argument_t instruction::s_arguments[instruction::Count] = {
|
|||||||
instruction_argument::None,
|
instruction_argument::None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::size_t instruction::read(std::string_view in) {
|
||||||
|
type = static_cast<type_e>(in[0]);
|
||||||
|
if (type >= Count) throw std::runtime_error("invalid instruction");
|
||||||
|
arg.type = s_arguments[type];
|
||||||
|
|
||||||
|
std::string_view argView = in.substr(1, arg.size());
|
||||||
|
switch (argView.size()) {
|
||||||
|
case 1: arg.u8 = argView[0]; break;
|
||||||
|
case 2: arg.u16 = argView[0] | (argView[1] << 8); break;
|
||||||
|
case 4: arg.u32 = argView[0] | (argView[1] << 8) | (argView[2] << 16) | (argView[3] << 24); break;
|
||||||
|
default: throw std::runtime_error("unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1 + argView.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t instruction::write(std::string& out) const {
|
||||||
|
if (type >= Count) throw std::runtime_error("invalid instruction");
|
||||||
|
if (s_arguments[type] != arg.type) throw std::runtime_error("malformed instruction");
|
||||||
|
out += static_cast<char>(type);
|
||||||
|
switch (arg.size()) {
|
||||||
|
case 1: out += arg.is_signed() ? std::to_string(arg.s8) : std::to_string(arg.u8); break;
|
||||||
|
case 2: out += arg.is_signed() ? std::to_string(arg.s16) : std::to_string(arg.u16); break;
|
||||||
|
case 4: out += arg.is_signed() ? std::to_string(arg.s32) : std::to_string(arg.u32); break;
|
||||||
|
default: throw std::runtime_error("unreachable");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace furvm
|
||||||
|
|||||||
Reference in New Issue
Block a user