134 lines
2.2 KiB
C++
134 lines
2.2 KiB
C++
#pragma once
|
|
|
|
#include "io_device.hpp"
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <span>
|
|
#include <utility>
|
|
|
|
namespace vc5 {
|
|
|
|
enum class Op : uint16_t {
|
|
Nop,
|
|
Hlt,
|
|
Jmp,
|
|
Jnz,
|
|
Mov,
|
|
LoadWord,
|
|
StoreWord,
|
|
LoadByte,
|
|
StoreByte,
|
|
Cmp,
|
|
Or,
|
|
And,
|
|
Xor,
|
|
Shl,
|
|
RShl,
|
|
Shr,
|
|
RShr,
|
|
Add,
|
|
Sub,
|
|
RSub,
|
|
|
|
// return from interrupt
|
|
RetI,
|
|
// load video character display
|
|
LVCD,
|
|
// load keyboard
|
|
LKBD,
|
|
};
|
|
|
|
const char* op_str(Op op);
|
|
|
|
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,
|
|
};
|
|
|
|
struct VcdDescript {
|
|
uint16_t map_base_addr;
|
|
};
|
|
|
|
struct KbdDescript {
|
|
uint16_t status_addr;
|
|
uint16_t keycode_addr;
|
|
uint16_t int_handler;
|
|
};
|
|
|
|
enum class KbdStatusFlag : uint16_t {
|
|
/// 0 Press
|
|
/// 1 Release
|
|
Type = 0,
|
|
Shift = 1,
|
|
Ctrl = 2,
|
|
Alt = 3,
|
|
AltGr = 4,
|
|
};
|
|
|
|
class VM {
|
|
public:
|
|
VM(IoDevice& device)
|
|
: m_device(&device)
|
|
{
|
|
}
|
|
|
|
void load(uint16_t offset, const uint8_t* data, size_t data_size);
|
|
int run();
|
|
|
|
auto reg(Reg reg) const -> uint16_t;
|
|
auto word(uint16_t addr) const -> uint16_t;
|
|
auto byte(uint16_t addr) const -> uint8_t;
|
|
|
|
void set_reg(Reg reg, uint16_t value);
|
|
void set_word(uint16_t addr, uint16_t value);
|
|
void set_byte(uint16_t addr, uint8_t value);
|
|
|
|
uint16_t eat_word();
|
|
|
|
private:
|
|
int run_instruction();
|
|
void poll_events();
|
|
|
|
void vcd_maybe_send_byte(uint16_t addr, uint8_t value);
|
|
|
|
void interrupt(uint16_t handler_addr);
|
|
|
|
std::array<uint8_t, 65536> m_mem = {};
|
|
std::array<uint16_t, 10> m_regs = {};
|
|
|
|
uint16_t* m_rsp = &m_regs[std::to_underlying(Reg::Rsp)];
|
|
uint16_t* m_rfl = &m_regs[std::to_underlying(Reg::Rfl)];
|
|
uint16_t* m_rip = &m_regs[std::to_underlying(Reg::Rip)];
|
|
|
|
IoDevice* m_device;
|
|
|
|
bool m_on = true;
|
|
bool m_halted = false;
|
|
bool m_interrupts_enabled = true;
|
|
bool m_vcd_loaded = false;
|
|
bool m_kbd_loaded = false;
|
|
|
|
VcdDescript m_vcd_descriptor {};
|
|
KbdDescript m_kbd_descriptor {};
|
|
};
|
|
|
|
}
|