init
This commit is contained in:
commit
3116ec1a13
14
.clang-format
Normal file
14
.clang-format
Normal file
@ -0,0 +1,14 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: WebKit
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 80
|
||||
IndentCaseLabels: true
|
||||
InsertNewlineAtEOF: true
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
|
||||
BinPackArguments: false
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
|
||||
BinPackParameters: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
build/
|
||||
27
Makefile
Normal file
27
Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
MAKEFLAGS += -j16
|
||||
|
||||
CXXFLAGS := -std=c++23 -Wall -Wextra -pedantic-errors -fsanitize=address,undefined
|
||||
LDFLAGS :=
|
||||
|
||||
build_dir = build
|
||||
obj_dir = $(build_dir)/obj
|
||||
|
||||
sources := $(shell find src/ -name *.cpp)
|
||||
|
||||
all: $(build_dir)/vc5
|
||||
|
||||
$(build_dir)/vc5: $(sources:%.cpp=$(obj_dir)/%.o)
|
||||
@mkdir -p $(dir $@)
|
||||
g++ $^ -o $@ $(CXXFLAGS) $(LDFLAGS)
|
||||
|
||||
$(obj_dir)/%.o: %.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
g++ $< -c -o $@ -MMD -MP $(CXXFLAGS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(build_dir)
|
||||
|
||||
-include $(sources:%.cpp=$(obj_dir)/%.d)
|
||||
|
||||
10
compile_flags.txt
Normal file
10
compile_flags.txt
Normal file
@ -0,0 +1,10 @@
|
||||
-xc++
|
||||
-std=c++23
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wpedantic
|
||||
-Wconversion
|
||||
-pedantic
|
||||
-pedantic-errors
|
||||
-Wno-unused-variable
|
||||
|
||||
185
src/builder.cpp
Normal file
185
src/builder.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
#include "builder.hpp"
|
||||
#include "vm.hpp"
|
||||
#include <utility>
|
||||
|
||||
using namespace vc5;
|
||||
|
||||
void Builder::nop()
|
||||
{
|
||||
auto ins = std::to_underlying(Op::Nop);
|
||||
push(ins);
|
||||
}
|
||||
|
||||
void Builder::hlt()
|
||||
{
|
||||
auto ins = std::to_underlying(Op::Nop);
|
||||
push(ins);
|
||||
}
|
||||
|
||||
void Builder::jmp_reg(Reg op1)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::jmp_imm(uint16_t op1)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::jnz_reg(Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::jnz_imm(Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_word_load_reg(Reg dst, Reg src)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_word_load_imm(Reg dst, uint16_t imm)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_word_load_mem_reg(Reg dst, Reg addr, uint16_t offset)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_word_load_mem_imm(Reg dst, uint16_t addr)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_word_store_reg_reg(Reg dst, uint16_t offset, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_word_store_reg_imm(Reg dst, uint16_t offset, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_word_store_imm_reg(uint16_t dst, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_word_store_imm_imm(uint16_t dst, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_byte_load_reg(Reg dst, Reg src)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_byte_load_imm(Reg dst, uint8_t imm)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_byte_load_mem_reg(Reg dst, Reg addr, uint16_t offset)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_byte_load_mem_imm(Reg dst, uint16_t addr)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_byte_store_reg_reg(Reg dst, uint16_t offset, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_byte_store_reg_imm(Reg dst, uint16_t offset, uint8_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_byte_store_imm_reg(uint16_t dst, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::mov_byte_store_imm_imm(uint16_t dst, uint8_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::cmp_reg(Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::cmp_imm(Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::or_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::and_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::xor_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::shl_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::rshl_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::shr_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::rshr_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::add_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::sub_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::rsub_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::or_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::and_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::xor_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::shl_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::rshl_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::shr_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::rshr_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::add_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::sub_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
|
||||
void Builder::rsub_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
}
|
||||
72
src/builder.hpp
Normal file
72
src/builder.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "vm.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace vc5 {
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
Builder(uint8_t* data)
|
||||
: m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
void nop();
|
||||
void hlt();
|
||||
void jmp_reg(Reg op1);
|
||||
void jmp_imm(uint16_t op1);
|
||||
void jnz_reg(Reg op1, Reg op2);
|
||||
void jnz_imm(Reg op1, uint16_t op2);
|
||||
void mov_word_load_reg(Reg dst, Reg src);
|
||||
void mov_word_load_imm(Reg dst, uint16_t imm);
|
||||
void mov_word_load_mem_reg(Reg dst, Reg addr, uint16_t offset);
|
||||
void mov_word_load_mem_imm(Reg dst, uint16_t addr);
|
||||
void mov_word_store_reg_reg(Reg dst, uint16_t offset, Reg op2);
|
||||
void mov_word_store_reg_imm(Reg dst, uint16_t offset, uint16_t op2);
|
||||
void mov_word_store_imm_reg(uint16_t dst, Reg op2);
|
||||
void mov_word_store_imm_imm(uint16_t dst, uint16_t op2);
|
||||
void mov_byte_load_reg(Reg dst, Reg src);
|
||||
void mov_byte_load_imm(Reg dst, uint8_t imm);
|
||||
void mov_byte_load_mem_reg(Reg dst, Reg addr, uint16_t offset);
|
||||
void mov_byte_load_mem_imm(Reg dst, uint16_t addr);
|
||||
void mov_byte_store_reg_reg(Reg dst, uint16_t offset, Reg op2);
|
||||
void mov_byte_store_reg_imm(Reg dst, uint16_t offset, uint8_t op2);
|
||||
void mov_byte_store_imm_reg(uint16_t dst, Reg op2);
|
||||
void mov_byte_store_imm_imm(uint16_t dst, uint8_t op2);
|
||||
void cmp_reg(Reg op1, Reg op2);
|
||||
void cmp_imm(Reg op1, Reg op2);
|
||||
void or_reg(Reg dst, Reg op1, Reg op2);
|
||||
void and_reg(Reg dst, Reg op1, Reg op2);
|
||||
void xor_reg(Reg dst, Reg op1, Reg op2);
|
||||
void shl_reg(Reg dst, Reg op1, Reg op2);
|
||||
void rshl_reg(Reg dst, Reg op1, Reg op2);
|
||||
void shr_reg(Reg dst, Reg op1, Reg op2);
|
||||
void rshr_reg(Reg dst, Reg op1, Reg op2);
|
||||
void add_reg(Reg dst, Reg op1, Reg op2);
|
||||
void sub_reg(Reg dst, Reg op1, Reg op2);
|
||||
void rsub_reg(Reg dst, Reg op1, Reg op2);
|
||||
void or_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void and_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void xor_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void shl_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void rshl_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void shr_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void rshr_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void add_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void sub_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void rsub_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
|
||||
private:
|
||||
inline void push(uint16_t v)
|
||||
{
|
||||
m_data[m_ip] = v >> 16;
|
||||
m_data[m_ip + 1] = v & 0xff;
|
||||
m_ip += 2;
|
||||
}
|
||||
|
||||
uint8_t* m_data;
|
||||
size_t m_ip = 0;
|
||||
};
|
||||
|
||||
}
|
||||
6
src/main.cpp
Normal file
6
src/main.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include <print>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::println("hello world");
|
||||
}
|
||||
202
src/vm.cpp
Normal file
202
src/vm.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
#include "vm.hpp"
|
||||
#include <cstdint>
|
||||
#include <print>
|
||||
|
||||
using namespace vc5;
|
||||
|
||||
int VM::run()
|
||||
{
|
||||
m_halted = false;
|
||||
while (not m_halted) {
|
||||
int result = run_instruction();
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VM::run_instruction()
|
||||
{
|
||||
auto ins = eat_ins();
|
||||
auto op = static_cast<Op>(ins & 0b11'1111);
|
||||
|
||||
switch (op) {
|
||||
case Op::Nop:
|
||||
break;
|
||||
case Op::Hlt:
|
||||
m_halted = true;
|
||||
break;
|
||||
case Op::Jmp: {
|
||||
auto op1 = ins.op1_or_imm();
|
||||
*m_rip = op1;
|
||||
break;
|
||||
}
|
||||
case Op::Jnz: {
|
||||
auto op1 = ins.op1();
|
||||
auto op2 = ins.op2_or_imm();
|
||||
|
||||
if (op1 != 0) {
|
||||
*m_rip = op2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Op::MovWord: {
|
||||
bool is_memory = ins >> 10 & 1;
|
||||
bool addr_is_reg = ins >> 11 & 1;
|
||||
bool is_store = ins >> 12 & 1;
|
||||
|
||||
if (!is_memory) {
|
||||
auto src = ins.reg_val_or_imm(6, 7, 0b1111);
|
||||
auto dst = static_cast<uint16_t>(ins >> 12 & 0b1111);
|
||||
m_regs[dst] = src;
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t addr;
|
||||
if (addr_is_reg) {
|
||||
auto reg = is_store ? ins.dst_reg() : ins.op2_reg();
|
||||
auto offset = static_cast<int16_t>(eat());
|
||||
addr = static_cast<uint16_t>(
|
||||
static_cast<int16_t>(m_regs[reg]) + offset);
|
||||
} else {
|
||||
addr = eat();
|
||||
}
|
||||
|
||||
if ((addr & 0b1) != 0) {
|
||||
std::println(stderr, "error: invalid address alignment");
|
||||
*m_rfl |= 1 << flag(Flag::Err);
|
||||
goto halt_execution;
|
||||
}
|
||||
|
||||
if (is_store) {
|
||||
auto src = ins.op2_or_imm();
|
||||
m_mem[addr] = src >> 16;
|
||||
m_mem[addr + 1] = src & 0xff;
|
||||
} else {
|
||||
auto reg = ins.dst_reg();
|
||||
|
||||
uint16_t value = 0;
|
||||
value |= static_cast<uint16_t>(m_mem[addr]) << 16;
|
||||
value |= m_mem[addr + 1];
|
||||
|
||||
m_regs[reg] = value;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Op::MovByte: {
|
||||
bool is_memory = ins >> 10 & 1;
|
||||
bool addr_is_reg = ins >> 11 & 1;
|
||||
bool is_store = ins >> 12 & 1;
|
||||
|
||||
if (!is_memory) {
|
||||
auto src = ins.reg_val_or_imm(6, 7, 0b1111);
|
||||
auto dst = static_cast<uint16_t>(ins >> 12 & 0b1111);
|
||||
m_regs[dst] = src & 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t addr;
|
||||
if (addr_is_reg) {
|
||||
auto reg = is_store ? ins.dst_reg() : ins.op2_reg();
|
||||
auto offset = static_cast<int16_t>(eat());
|
||||
addr = static_cast<uint16_t>(
|
||||
static_cast<int16_t>(m_regs[reg]) + offset);
|
||||
} else {
|
||||
addr = eat();
|
||||
}
|
||||
|
||||
if (is_store) {
|
||||
auto src = ins.op2_or_imm();
|
||||
m_mem[addr] = src & 0xff;
|
||||
} else {
|
||||
auto reg = ins.dst_reg();
|
||||
|
||||
uint16_t value = 0;
|
||||
value |= static_cast<uint16_t>(m_mem[addr]) << 16;
|
||||
value |= m_mem[addr + 1];
|
||||
|
||||
m_regs[reg] = value;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Op::Cmp: {
|
||||
auto op1 = ins.op1();
|
||||
auto op2 = ins.op2_or_imm();
|
||||
|
||||
if (op1 == op2) {
|
||||
*m_rfl |= 1u << flag(Flag::Eq);
|
||||
} else {
|
||||
*m_rfl &= (uint16_t)~(1u << flag(Flag::Eq));
|
||||
}
|
||||
if (op1 < op2) {
|
||||
*m_rfl |= 1u << flag(Flag::Be);
|
||||
} else {
|
||||
*m_rfl &= (uint16_t)~(1u << flag(Flag::Be));
|
||||
}
|
||||
if ((int16_t)op1 < (int16_t)op2) {
|
||||
*m_rfl |= 1u << flag(Flag::Lt);
|
||||
} else {
|
||||
*m_rfl &= (uint16_t)~(1u << flag(Flag::Lt));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Op::Or:
|
||||
case Op::And:
|
||||
case Op::Xor:
|
||||
case Op::Shl:
|
||||
case Op::RShl:
|
||||
case Op::Shr:
|
||||
case Op::RShr:
|
||||
case Op::Add:
|
||||
case Op::Sub:
|
||||
case Op::RSub: {
|
||||
auto op1 = ins.op1();
|
||||
auto op2 = ins.op2_or_imm();
|
||||
auto dst_reg = ins.dst_reg();
|
||||
|
||||
uint16_t* dst = &m_regs[dst_reg];
|
||||
|
||||
switch (op) {
|
||||
case Op::Or:
|
||||
*dst = op1 | op2;
|
||||
break;
|
||||
case Op::Xor:
|
||||
*dst = op1 ^ op2;
|
||||
break;
|
||||
case Op::And:
|
||||
*dst = op1 & op2;
|
||||
break;
|
||||
case Op::Shl:
|
||||
*dst = static_cast<uint16_t>(op1 << op2);
|
||||
break;
|
||||
case Op::RShl:
|
||||
*dst = static_cast<uint16_t>(op2 << op1);
|
||||
break;
|
||||
case Op::Shr:
|
||||
*dst = static_cast<uint16_t>(op1 >> op2);
|
||||
break;
|
||||
case Op::RShr:
|
||||
*dst = static_cast<uint16_t>(op2 >> op1);
|
||||
break;
|
||||
case Op::Add:
|
||||
*dst = op1 + op2;
|
||||
break;
|
||||
case Op::Sub:
|
||||
*dst = op1 - op2;
|
||||
break;
|
||||
case Op::RSub:
|
||||
*dst = op2 - op1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
halt_execution:
|
||||
return 0;
|
||||
}
|
||||
155
src/vm.hpp
Normal file
155
src/vm.hpp
Normal file
@ -0,0 +1,155 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user