add disk
This commit is contained in:
parent
2e7ab57cc1
commit
2b423a40ed
@ -3,19 +3,30 @@
|
|||||||
%define KBD_CODE 0x1ffe
|
%define KBD_CODE 0x1ffe
|
||||||
%define VCD 0x2000
|
%define VCD 0x2000
|
||||||
|
|
||||||
%define FL_EQ 1 << 1
|
%define FL_EQ 0x2
|
||||||
|
%define FL_EQ 0x4
|
||||||
|
|
||||||
%define KBD_FLAG_IS_RELEASE 0x1
|
%define KBD_FLAG_IS_RELEASE 0x1
|
||||||
|
|
||||||
mov rsp, 0x1000
|
mov rsp, 0x1000
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
|
|
||||||
; setup vcd
|
mov r0, 512
|
||||||
|
mov r1, 1
|
||||||
|
dskr r0, r1
|
||||||
|
|
||||||
|
; setup video character display (VCD)
|
||||||
|
; descriptor table structure:
|
||||||
|
; [addr + 0] memory map base
|
||||||
mov r0, VCD
|
mov r0, VCD
|
||||||
mov [0x700], r0
|
mov [0x700], r0
|
||||||
lvcd 0x700
|
lvcd 0x700
|
||||||
|
|
||||||
; setup kbd
|
; setup keyboard (KBD)
|
||||||
|
; descriptor table structure:
|
||||||
|
; [addr + 0] status address
|
||||||
|
; [addr + 2] keycode address
|
||||||
|
; [addr + 4] keyboard interrupt handler
|
||||||
mov r0, KBD_STATUS
|
mov r0, KBD_STATUS
|
||||||
mov [0x702], r0
|
mov [0x702], r0
|
||||||
mov r0, KBD_CODE
|
mov r0, KBD_CODE
|
||||||
@ -24,7 +35,7 @@
|
|||||||
mov [0x706], r0
|
mov [0x706], r0
|
||||||
lkbd 0x702
|
lkbd 0x702
|
||||||
|
|
||||||
; init counter
|
; character counter
|
||||||
mov r0, 0
|
mov r0, 0
|
||||||
mov [0x600], r0
|
mov [0x600], r0
|
||||||
|
|
||||||
@ -50,10 +61,31 @@ key_press_int:
|
|||||||
mov r0, [0x600]
|
mov r0, [0x600]
|
||||||
add r0, r0, 1
|
add r0, r0, 1
|
||||||
mov [0x600], r0
|
mov [0x600], r0
|
||||||
|
|
||||||
.leave:
|
.leave:
|
||||||
reti
|
reti
|
||||||
|
|
||||||
|
scancode_to_char:
|
||||||
|
cmp r1, 61
|
||||||
|
|
||||||
|
mov r2, rfl
|
||||||
|
and r2, r2, FL_LT
|
||||||
|
jnz .not_letter
|
||||||
|
|
||||||
|
; if r1 > 86 { goto .not_letter }
|
||||||
|
cmp r1, 86
|
||||||
|
mov r2, rfl
|
||||||
|
xor r2, 0xffff
|
||||||
|
and r2, r2, FL_EQ | FL_LT
|
||||||
|
|
||||||
|
|
||||||
|
mov r4, rfl
|
||||||
|
and r4, r4, FL_EQ
|
||||||
|
shr r4, r4, 2
|
||||||
|
|
||||||
|
.not_letter:
|
||||||
|
|
||||||
|
|
||||||
|
61 >= 61
|
||||||
|
|
||||||
; vim: syntax=nasm
|
; vim: syntax=nasm
|
||||||
|
|
||||||
|
|||||||
36
src/block_device.cpp
Normal file
36
src/block_device.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "block_device.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <ios>
|
||||||
|
|
||||||
|
using namespace vc5;
|
||||||
|
|
||||||
|
void MemoryDisk::read(uint8_t* data, uint16_t block)
|
||||||
|
{
|
||||||
|
std::memcpy(data, &m_data[block * block_size], block_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDisk::write(const uint8_t* data, uint16_t block)
|
||||||
|
{
|
||||||
|
std::memcpy(&m_data[block * block_size], data, block_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto FileDisk::block_count() -> uint16_t
|
||||||
|
{
|
||||||
|
m_file.seekg(0, std::ios_base::end);
|
||||||
|
std::streamsize location = m_file.tellg();
|
||||||
|
return location / block_size & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDisk::read(uint8_t* data, uint16_t block)
|
||||||
|
{
|
||||||
|
m_file.seekg(block * block_size);
|
||||||
|
m_file.read(reinterpret_cast<char*>(data), block_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDisk::write(const uint8_t* data, uint16_t block)
|
||||||
|
{
|
||||||
|
m_file.seekg(block * block_size);
|
||||||
|
m_file.write(reinterpret_cast<const char*>(data), block_size);
|
||||||
|
}
|
||||||
66
src/block_device.hpp
Normal file
66
src/block_device.hpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <ios>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace vc5 {
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
class BlockDevice {
|
||||||
|
public:
|
||||||
|
virtual ~BlockDevice() = default;
|
||||||
|
|
||||||
|
static constexpr uint16_t block_size = 512;
|
||||||
|
|
||||||
|
virtual auto block_count() -> uint16_t = 0;
|
||||||
|
|
||||||
|
virtual void read(uint8_t* data, uint16_t block) = 0;
|
||||||
|
virtual void write(const uint8_t* data, uint16_t block) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MemoryDisk final : public BlockDevice {
|
||||||
|
public:
|
||||||
|
explicit MemoryDisk(uint16_t block_count)
|
||||||
|
: m_data(block_size * block_count, 0)
|
||||||
|
, m_block_count(block_count)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
auto block_count() -> uint16_t override
|
||||||
|
{
|
||||||
|
return m_block_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(uint8_t* data, uint16_t block) override;
|
||||||
|
void write(const uint8_t* data, uint16_t block) override;
|
||||||
|
|
||||||
|
auto data() -> uint8_t*
|
||||||
|
{
|
||||||
|
return m_data.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> m_data;
|
||||||
|
uint16_t m_block_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileDisk final : public BlockDevice {
|
||||||
|
public:
|
||||||
|
explicit FileDisk(fs::path file_path)
|
||||||
|
: m_file(file_path, std::ios_base::binary)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
auto block_count() -> uint16_t override;
|
||||||
|
void read(uint8_t* data, uint16_t block) override;
|
||||||
|
void write(const uint8_t* data, uint16_t block) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::fstream m_file;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@ -361,3 +361,19 @@ void Builder::lkbd_imm(uint16_t op1)
|
|||||||
i.imm(op1);
|
i.imm(op1);
|
||||||
i.build(*this);
|
i.build(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Builder::dskr(Reg dst, Reg op1)
|
||||||
|
{
|
||||||
|
auto i = InsBuilder(Op::DSKR);
|
||||||
|
i.dst_reg(dst);
|
||||||
|
i.op1_reg(op1);
|
||||||
|
i.build(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Builder::dskw(Reg dst, Reg op1)
|
||||||
|
{
|
||||||
|
auto i = InsBuilder(Op::DSKW);
|
||||||
|
i.dst_reg(dst);
|
||||||
|
i.op1_reg(op1);
|
||||||
|
i.build(*this);
|
||||||
|
}
|
||||||
|
|||||||
@ -58,6 +58,8 @@ public:
|
|||||||
void lvcd_imm(uint16_t op1);
|
void lvcd_imm(uint16_t op1);
|
||||||
void lkbd_reg(Reg op1);
|
void lkbd_reg(Reg op1);
|
||||||
void lkbd_imm(uint16_t op1);
|
void lkbd_imm(uint16_t op1);
|
||||||
|
void dskr(Reg dst, Reg op1);
|
||||||
|
void dskw(Reg dst, Reg op1);
|
||||||
|
|
||||||
uint16_t ip() const
|
uint16_t ip() const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -113,8 +113,6 @@ auto IoDevice::set_char(uint16_t offset, uint8_t value)
|
|||||||
{
|
{
|
||||||
auto lock = std::lock_guard(mx);
|
auto lock = std::lock_guard(mx);
|
||||||
|
|
||||||
std::println("char = '{}' or '{}'", static_cast<char>(value), value);
|
|
||||||
|
|
||||||
SDL_Color* buffer;
|
SDL_Color* buffer;
|
||||||
int pitch;
|
int pitch;
|
||||||
int res = SDL_LockTexture(m_texture, NULL, (void**)&buffer, &pitch);
|
int res = SDL_LockTexture(m_texture, NULL, (void**)&buffer, &pitch);
|
||||||
@ -161,7 +159,7 @@ auto IoDevice::set_char(uint16_t offset, uint8_t value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockTexture(m_texture);
|
SDL_UnlockTexture(m_texture);
|
||||||
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
|
SDL_RenderCopy(m_renderer, m_texture, nullptr, nullptr);
|
||||||
|
|
||||||
SDL_RenderPresent(m_renderer);
|
SDL_RenderPresent(m_renderer);
|
||||||
|
|
||||||
|
|||||||
54
src/main.cpp
54
src/main.cpp
@ -1,44 +1,32 @@
|
|||||||
|
#include "block_device.hpp"
|
||||||
#include "builder.hpp"
|
#include "builder.hpp"
|
||||||
#include "io_device.hpp"
|
#include "io_device.hpp"
|
||||||
#include "vm.hpp"
|
#include "vm.hpp"
|
||||||
#include <SDL2/SDL_main.h>
|
#include <SDL2/SDL_main.h>
|
||||||
#include <array>
|
|
||||||
#include <chrono>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <iostream>
|
|
||||||
#include <print>
|
#include <print>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
using namespace vc5;
|
using namespace vc5;
|
||||||
using R = Reg;
|
using namespace vc5::regs;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
auto device = IoDevice::create().value();
|
auto device = IoDevice::create().value();
|
||||||
|
device->set_title("vc5");
|
||||||
|
|
||||||
constexpr R r0 = R::R0;
|
auto disk = MemoryDisk(128);
|
||||||
constexpr R r1 = R::R1;
|
|
||||||
constexpr R r2 = R::R2;
|
|
||||||
constexpr R r3 = R::R3;
|
|
||||||
constexpr R r4 = R::R4;
|
|
||||||
constexpr R r5 = R::R5;
|
|
||||||
constexpr R rbp = R::Rbp;
|
|
||||||
constexpr R rsp = R::Rsp;
|
|
||||||
constexpr R rfl = R::Rfl;
|
|
||||||
constexpr R rip = R::Rip;
|
|
||||||
|
|
||||||
auto program = std::array<uint8_t, 65536>();
|
auto l = Builder(disk.data());
|
||||||
|
|
||||||
auto l = Builder(program.data());
|
|
||||||
|
|
||||||
l.mov_imm(rsp, 0x1000);
|
l.mov_imm(rsp, 0x1000);
|
||||||
l.mov_reg(rbp, rsp);
|
l.mov_reg(rbp, rsp);
|
||||||
|
|
||||||
|
l.mov_imm(r0, 512);
|
||||||
|
l.mov_imm(r1, 1);
|
||||||
|
l.dskr(r0, r1);
|
||||||
|
|
||||||
l.mov_imm(r0, 0x2000);
|
l.mov_imm(r0, 0x2000);
|
||||||
l.store_word_imm(0x700, r0);
|
l.store_word_imm(0x700, r0);
|
||||||
l.lvcd_imm(0x700);
|
l.lvcd_imm(0x700);
|
||||||
@ -70,7 +58,7 @@ int main()
|
|||||||
l.load_word_imm(r1, 0x1ffe);
|
l.load_word_imm(r1, 0x1ffe);
|
||||||
l.cmp_imm(r1, 44);
|
l.cmp_imm(r1, 44);
|
||||||
l.mov_reg(r2, rfl);
|
l.mov_reg(r2, rfl);
|
||||||
l.and_imm(r2, r2, 1 << std::to_underlying(Flag::Eq));
|
l.and_imm(r2, r2, 2);
|
||||||
auto to_set_key_press_incr = l.ip();
|
auto to_set_key_press_incr = l.ip();
|
||||||
l.jnz_imm(r2, 0);
|
l.jnz_imm(r2, 0);
|
||||||
l.add_imm(r1, r1, 61);
|
l.add_imm(r1, r1, 61);
|
||||||
@ -90,28 +78,8 @@ int main()
|
|||||||
l.set_ip(to_set_key_press_int_leave + 2);
|
l.set_ip(to_set_key_press_int_leave + 2);
|
||||||
l.push(key_press_int_leave);
|
l.push(key_press_int_leave);
|
||||||
|
|
||||||
auto vm = VM(*device);
|
auto vm = VM(*device, disk);
|
||||||
vm.load(0, program.data(), program.size());
|
|
||||||
|
|
||||||
device->set_title("vc5");
|
|
||||||
|
|
||||||
vm.run();
|
vm.run();
|
||||||
|
|
||||||
std::println("--- regs ---");
|
|
||||||
std::println("r0\t{}", vm.reg(r0));
|
|
||||||
std::println("r1\t{}", vm.reg(r1));
|
|
||||||
std::println("r2\t{}", vm.reg(r2));
|
|
||||||
std::println("r3\t{}", vm.reg(r3));
|
|
||||||
std::println("r4\t{}", vm.reg(r4));
|
|
||||||
std::println("r5\t{}", vm.reg(r5));
|
|
||||||
std::println("rbp\t{}", vm.reg(rbp));
|
|
||||||
std::println("rsp\t{}", vm.reg(rsp));
|
|
||||||
std::println("rfl\t{}", vm.reg(rfl));
|
|
||||||
std::println("rip\t{}", vm.reg(rip));
|
|
||||||
std::println("--- mem ---");
|
|
||||||
for (uint16_t i = 0; i < 32; i += 2) {
|
|
||||||
std::println("{: 4x}\t{}", i, vm.word(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" const char* __asan_default_options(void)
|
extern "C" const char* __asan_default_options(void)
|
||||||
|
|||||||
22
src/vm.cpp
22
src/vm.cpp
@ -18,6 +18,11 @@ void VM::load(uint16_t offset, const uint8_t* data, size_t data_size)
|
|||||||
|
|
||||||
int VM::run()
|
int VM::run()
|
||||||
{
|
{
|
||||||
|
constexpr uint16_t bootloader_size = 512;
|
||||||
|
for (uint16_t i = 0; i * m_disk->block_size < bootloader_size; ++i) {
|
||||||
|
m_disk->read(&m_mem[i * m_disk->block_size], i);
|
||||||
|
}
|
||||||
|
|
||||||
m_on = true;
|
m_on = true;
|
||||||
while (m_on) {
|
while (m_on) {
|
||||||
if (not m_halted) {
|
if (not m_halted) {
|
||||||
@ -405,6 +410,19 @@ int VM::run_instruction()
|
|||||||
.int_handler = word(op1 + 4),
|
.int_handler = word(op1 + 4),
|
||||||
};
|
};
|
||||||
m_kbd_loaded = true;
|
m_kbd_loaded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op::DSKR: {
|
||||||
|
auto addr = ins.dst();
|
||||||
|
auto block = ins.op1();
|
||||||
|
m_disk->read(&m_mem[addr], block);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op::DSKW: {
|
||||||
|
auto addr = ins.op1();
|
||||||
|
auto block = ins.dst();
|
||||||
|
m_disk->write(&m_mem[addr], block);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,6 +550,10 @@ const char* vc5::op_str(Op op)
|
|||||||
return "LVCD";
|
return "LVCD";
|
||||||
case Op::LKBD:
|
case Op::LKBD:
|
||||||
return "LKBD";
|
return "LKBD";
|
||||||
|
case Op::DSKR:
|
||||||
|
return "DSKR";
|
||||||
|
case Op::DSKW:
|
||||||
|
return "DSKW";
|
||||||
}
|
}
|
||||||
return ">.<";
|
return ">.<";
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/vm.hpp
23
src/vm.hpp
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "block_device.hpp"
|
||||||
#include "io_device.hpp"
|
#include "io_device.hpp"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -38,6 +39,11 @@ enum class Op : uint16_t {
|
|||||||
LVCD,
|
LVCD,
|
||||||
// load keyboard
|
// load keyboard
|
||||||
LKBD,
|
LKBD,
|
||||||
|
|
||||||
|
// disk read
|
||||||
|
DSKR,
|
||||||
|
// disk write
|
||||||
|
DSKW,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* op_str(Op op);
|
const char* op_str(Op op);
|
||||||
@ -55,6 +61,19 @@ enum class Reg : uint16_t {
|
|||||||
Rip = 9,
|
Rip = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace regs {
|
||||||
|
constexpr Reg r0 = Reg::R0;
|
||||||
|
constexpr Reg r1 = Reg::R1;
|
||||||
|
constexpr Reg r2 = Reg::R2;
|
||||||
|
constexpr Reg r3 = Reg::R3;
|
||||||
|
constexpr Reg r4 = Reg::R4;
|
||||||
|
constexpr Reg r5 = Reg::R5;
|
||||||
|
constexpr Reg rbp = Reg::Rbp;
|
||||||
|
constexpr Reg rsp = Reg::Rsp;
|
||||||
|
constexpr Reg rfl = Reg::Rfl;
|
||||||
|
constexpr Reg rip = Reg::Rip;
|
||||||
|
}
|
||||||
|
|
||||||
enum class Flag : uint16_t {
|
enum class Flag : uint16_t {
|
||||||
Zero = 0,
|
Zero = 0,
|
||||||
Eq = 1,
|
Eq = 1,
|
||||||
@ -85,8 +104,9 @@ enum class KbdStatusFlag : uint16_t {
|
|||||||
|
|
||||||
class VM {
|
class VM {
|
||||||
public:
|
public:
|
||||||
VM(IoDevice& device)
|
VM(IoDevice& device, BlockDevice& disk)
|
||||||
: m_device(&device)
|
: m_device(&device)
|
||||||
|
, m_disk(&disk)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +139,7 @@ private:
|
|||||||
uint16_t* m_rip = &m_regs[std::to_underlying(Reg::Rip)];
|
uint16_t* m_rip = &m_regs[std::to_underlying(Reg::Rip)];
|
||||||
|
|
||||||
IoDevice* m_device;
|
IoDevice* m_device;
|
||||||
|
BlockDevice* m_disk;
|
||||||
|
|
||||||
bool m_on = true;
|
bool m_on = true;
|
||||||
bool m_halted = false;
|
bool m_halted = false;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user