156 lines
2.6 KiB
C++
156 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <utility>
|
|
|
|
namespace vc5 {
|
|
|
|
enum class Op : uint16_t {
|
|
Nop,
|
|
Hlt,
|
|
Jmp,
|
|
Jnz,
|
|
MovWord,
|
|
MovByte,
|
|
Cmp,
|
|
Or,
|
|
And,
|
|
Xor,
|
|
Shl,
|
|
RShl,
|
|
Shr,
|
|
RShr,
|
|
Add,
|
|
Sub,
|
|
RSub,
|
|
};
|
|
|
|
enum class Reg : uint16_t {
|
|
R0 = 0,
|
|
R1 = 1,
|
|
R2 = 2,
|
|
R3 = 3,
|
|
R4 = 4,
|
|
R5 = 5,
|
|
Rbp = 6,
|
|
Rsp = 7,
|
|
Rfl = 8,
|
|
Rip = 9,
|
|
};
|
|
|
|
enum class Flag : uint16_t {
|
|
Zero = 0,
|
|
Eq = 1,
|
|
Be = 2,
|
|
Lt = 3,
|
|
Err = 4,
|
|
};
|
|
|
|
class VM {
|
|
public:
|
|
struct Ins {
|
|
Ins(VM& vm, uint16_t ins)
|
|
: vm(&vm)
|
|
, ins(ins)
|
|
{
|
|
}
|
|
|
|
VM* vm;
|
|
uint16_t ins;
|
|
|
|
operator uint16_t()
|
|
{
|
|
return ins;
|
|
}
|
|
|
|
inline uint16_t dst_reg() const
|
|
{
|
|
return ins >> 13 & 0b111;
|
|
}
|
|
|
|
inline uint16_t op1_reg() const
|
|
{
|
|
return ins >> 10 & 0b111;
|
|
}
|
|
|
|
inline uint16_t op2_reg() const
|
|
{
|
|
return ins >> 7 & 0b111;
|
|
}
|
|
|
|
inline uint16_t op1() const
|
|
{
|
|
return vm->m_regs[op1_reg()];
|
|
}
|
|
|
|
inline uint16_t op2() const
|
|
{
|
|
|
|
return vm->m_regs[op2_reg()];
|
|
}
|
|
|
|
inline uint16_t op1_or_imm()
|
|
{
|
|
return reg_val_or_imm(6, 10, 0b111);
|
|
}
|
|
|
|
inline uint16_t op2_or_imm()
|
|
{
|
|
return reg_val_or_imm(6, 7, 0b111);
|
|
}
|
|
|
|
inline uint16_t reg_val_or_imm(
|
|
uint16_t is_imm_bit, uint16_t reg_bit, uint16_t reg_mask)
|
|
{
|
|
bool is_imm = (ins >> is_imm_bit & 1) != 0;
|
|
if (is_imm) {
|
|
return vm->eat();
|
|
} else {
|
|
return vm->m_regs[ins >> reg_bit & reg_mask];
|
|
}
|
|
}
|
|
};
|
|
|
|
int run();
|
|
|
|
private:
|
|
int run_instruction();
|
|
|
|
inline uint16_t eat()
|
|
{
|
|
uint16_t ins = 0;
|
|
ins |= static_cast<uint16_t>(m_mem[*m_rip]) << 16;
|
|
ins |= m_mem[*m_rip + 1];
|
|
*m_rip += 2;
|
|
return ins;
|
|
}
|
|
|
|
inline Ins eat_ins()
|
|
{
|
|
auto ins = eat();
|
|
return Ins(*this, ins);
|
|
}
|
|
|
|
static constexpr uint16_t reg(Reg reg)
|
|
{
|
|
return std::to_underlying(reg);
|
|
}
|
|
|
|
static constexpr uint16_t flag(Flag flag)
|
|
{
|
|
return std::to_underlying(flag);
|
|
}
|
|
|
|
std::array<uint8_t, 65536> m_mem = {};
|
|
std::array<uint16_t, 8> m_regs = {};
|
|
|
|
uint16_t* m_rfl = &m_regs[reg(Reg::Rfl)];
|
|
uint16_t* m_rip = &m_regs[reg(Reg::Rip)];
|
|
|
|
bool m_halted = false;
|
|
};
|
|
|
|
}
|