working visualization of the vm

This commit is contained in:
shylie 2025-03-07 02:58:45 -05:00
parent 6ab27289a8
commit d58425bf75
6 changed files with 2210 additions and 25 deletions

2087
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,3 +6,8 @@ edition = "2021"
[dependencies] [dependencies]
byteorder = "1" byteorder = "1"
customasm = "0.13.9" customasm = "0.13.9"
pixels = "0.15"
[dependencies.winit]
version = "0.30"
features = ["rwh_05"]

11
examples/first.asm Normal file
View File

@ -0,0 +1,11 @@
;#include "../src/foot.asm"
CNST. r0, 0xFBFF
CNST. r29, 0x400
label:
CNST.r [r0++], 0b1100110011001100
CNST. r31, label
data:

View File

@ -1,3 +1,5 @@
#once
#subruledef operand #subruledef operand
{ {
#{immediate: s5} => 0b000 @ immediate #{immediate: s5} => 0b000 @ immediate
@ -28,7 +30,7 @@
#ruledef #ruledef
{ {
CNST{flags: crflags} {dst: operand}, {imm: i16} => imm @ 0b0000 @ flags @ dst CNST{flags: crflags} {dst: operand}, {imm: i16} => imm @ flags @ 0b0000 @ dst
} }
#bankdef mem #bankdef mem

View File

@ -1,18 +1,111 @@
#![windows_subsystem = "windows"]
mod vm; mod vm;
use vm::{FootVM}; use std::sync::Arc;
use vm::FootVM;
use pixels::{Pixels, SurfaceTexture};
use winit::application::ApplicationHandler;
use winit::dpi::LogicalSize;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::window::{Window, WindowAttributes, WindowId};
pub struct App
{
vm: FootVM,
window: Option<Arc<Window>>,
pixels: Option<Pixels<'static>>
}
impl App
{
fn new(vm: FootVM) -> Self
{
App
{
vm,
window: None,
pixels: None
}
}
fn draw(&mut self)
{
let pixels = &mut self.pixels.as_mut().unwrap();
let frame = pixels.frame_mut();
for i in 0u16..32u16
{
for j in 0u16..32u16
{
let index = i + j * 32;
let mut value = self.vm[index + 0xFBFF];
for k in 0..16
{
let pixel_value = ((value & 1) * 255) as u8;
let pixel_index = (index as usize * 64) + k * 4;
frame[pixel_index + 0] = pixel_value;
frame[pixel_index + 1] = pixel_value;
frame[pixel_index + 2] = pixel_value;
frame[pixel_index + 3] = 0xFF;
value >>= 1;
}
}
}
pixels.render().expect("");
}
}
impl ApplicationHandler for App
{
fn resumed(&mut self, event_loop: &ActiveEventLoop)
{
const WIDTH: u32 = 128;
const HEIGHT: u32 = 128;
let window = event_loop.create_window(
WindowAttributes::default()
.with_resizable(false)
.with_inner_size(LogicalSize::new(WIDTH * 4, HEIGHT * 4))
.with_title("foot vm")
).unwrap();
let window = Arc::new(window);
self.window = Some(window);
let surface_texture = SurfaceTexture::new(WIDTH * 4, HEIGHT * 4, self.window.as_ref().unwrap().clone());
self.pixels = Some(Pixels::new(WIDTH, HEIGHT, surface_texture).unwrap());
}
fn window_event(&mut self, event_loop: &ActiveEventLoop, _: WindowId, event: WindowEvent)
{
self.vm.cycle();
match event
{
WindowEvent::RedrawRequested => self.draw(),
WindowEvent::CloseRequested => event_loop.exit(),
_ => {}
}
}
}
const ASM_SRC: &'static str = include_str!("../examples/first.asm");
fn main() fn main()
{ {
let mut vm = FootVM::new(); let mut vm = FootVM::new();
vm[0] = 0xFEED; vm.load(ASM_SRC, Some(&mut std::io::stderr())).expect("");
vm[1] = 0b0000_0000_001_00000;
let result = vm.load("CNST. r0, 0xBEEF", Some(&mut std::io::stderr())); let event_loop = EventLoop::new().unwrap();
if result.is_ok() event_loop.set_control_flow(ControlFlow::Poll);
{
vm.cycle();
println!("{}", vm.registers[0]); let mut app = App::new(vm);
} event_loop.run_app(&mut app).expect("");
} }

View File

@ -80,7 +80,7 @@ impl TryFrom<u32> for Operand
fn try_from(value: u32) -> Result<Self, Self::Error> fn try_from(value: u32) -> Result<Self, Self::Error>
{ {
match (value >> 5).try_into() match ((value >> 5) & 0b111).try_into()
{ {
Ok(addressing_mode) => Ok( Ok(addressing_mode) => Ok(
Operand Operand
@ -124,7 +124,8 @@ impl TryFrom<u32> for Instruction
let ceflag: ConditionalExecutionFlag = (value >> 29).try_into()?; let ceflag: ConditionalExecutionFlag = (value >> 29).try_into()?;
let rflag: bool = (value >> 28 & 1) == 1; let rflag: bool = (value >> 28 & 1) == 1;
let dst: Operand = (value >> 16).try_into()?; let dst: Operand = (value >> 16).try_into()?;
match value >> 24 let opcode = (value >> 24) & 0xF;
match opcode
{ {
0 => Ok(CNST(ceflag, rflag, dst, (value & 0xFFFF) as u16)), 0 => Ok(CNST(ceflag, rflag, dst, (value & 0xFFFF) as u16)),
1 => 1 =>
@ -178,10 +179,18 @@ const MEMORY_SIZE: usize = 1 << 16;
pub struct FootVM pub struct FootVM
{ {
memory: [u16; MEMORY_SIZE], memory: [u16; MEMORY_SIZE],
pub registers: [u16; 32], registers: [u16; 32],
status: Status status: Status
} }
impl Default for FootVM
{
fn default() -> Self
{
Self::new()
}
}
macro_rules! run_instruction macro_rules! run_instruction
{ {
($self:ident, $cef:ident, $rep:ident, $name:ident, $d:ident, $a:ident) => ($self:ident, $cef:ident, $rep:ident, $name:ident, $d:ident, $a:ident) =>