Skip to content

Commit

Permalink
simple assembler and vm
Browse files Browse the repository at this point in the history
  • Loading branch information
junaadh committed Aug 3, 2024
0 parents commit 41cf5a4
Show file tree
Hide file tree
Showing 21 changed files with 621 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[workspace]
members = [ "asm","jnd", "vm"]
resolver = "2"
6 changes: 6 additions & 0 deletions asm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "asm"
version = "0.1.0"
edition = "2021"

[dependencies]
29 changes: 29 additions & 0 deletions asm/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::{
env,
fs::File,
io::{self, Read, Write},
process::exit,
};

fn main() {
let args = env::args().collect::<Vec<_>>();

if args.len() < 2 {
println!("Usage: {} <file>", args[0]);
exit(1);
}

let mut file = File::open(&args[1]).expect("Failed to open file");
let mut buf = String::new();

file.read_to_string(&mut buf).unwrap();

let mut out = Vec::new();
for word in buf.split_whitespace() {
// let byte = word.parse::<u8>().unwrap();
let byte = u8::from_str_radix(word, 16).unwrap();
out.push(byte);
}
let mut stdout = io::stdout().lock();
stdout.write_all(&out).expect("Writing to stdout");
}
6 changes: 6 additions & 0 deletions jnd/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "jnd"
version = "0.1.0"
edition = "2021"

[dependencies]
28 changes: 28 additions & 0 deletions jnd/src/disassembler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::vm::Machine;

pub trait Disassemble {
fn print_reg(&self);
fn print_mem_map(&self);
}

impl Disassemble for Machine {
fn print_reg(&self) {
println!("== Registers ==");

for (i, &reg) in ["a", "b", "c", "m", "sp", "pc", "bp", "flags"]
.iter()
.enumerate()
{
println!(
" {reg:<7}: {}",
self.get_reg((i as u8).try_into().unwrap())
);
}

println!("===============");
}

fn print_mem_map(&self) {
todo!()
}
}
Empty file added jnd/src/errors/asme.rs
Empty file.
30 changes: 30 additions & 0 deletions jnd/src/errors/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use core::panic;

pub mod asme;
pub mod vme;

pub trait Erroring {
fn err(&self) -> &str;
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Jerror {
Vme(String),
Asme(String),
}

impl Jerror {
pub fn vme(&self, err: &str) -> Self {
match self {
Self::Vme(e) => Self::Vme(format!("{e}: {err}")),
_ => panic!("This shouldnt happen. Jerror::vme shoudlnt access asme"),
}
}

pub fn asme(&self, err: &str) -> Self {
match self {
Self::Asme(e) => Self::Asme(format!("{e}: {err}")),
_ => panic!("This shouldnt happen. Jerror::asme shoudlnt access vme"),
}
}
}
124 changes: 124 additions & 0 deletions jnd/src/errors/vme.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use core::fmt;

use super::Erroring;

#[derive(Debug)]
pub enum VMErr {
WriteOutOfBounds,
ReadOutOfBound,
InvalidRegister,
MemReadFail,
MemRead2Fail,
MemWriteFail,
MemWrite2Fail,
UnknownInstruction,
InterruptHandlerNotFound,
InterruptHandlerInsert,
}

impl Erroring for VMErr {
fn err(&self) -> &str {
match self {
Self::WriteOutOfBounds => "write out of bounds",
Self::ReadOutOfBound => "read out of bounds",
Self::InvalidRegister => "accessed register invalid",
Self::MemReadFail => "mem read failed",
Self::MemRead2Fail => "mem read 16bit failed",
Self::MemWriteFail => "mem write failed",
Self::MemWrite2Fail => "mem write 16bit failed",
Self::UnknownInstruction => "instruction unknown",
Self::InterruptHandlerNotFound => "no known handlers for the interrupt",
Self::InterruptHandlerInsert => "failed to insert interrupt handler",
}
}
}

impl fmt::Display for VMErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.err())
}
}

#[macro_export]
macro_rules! vme {
($err: expr, $kind: ident, $($args:tt)*) => {{
use $crate::errors::Erroring;
$err.vme(format!("{}: {}", $crate::errors::vme::VMErr::$kind.err(), format_args!($($args)*)).as_str())
}};

($kind:ident, $($args:tt)*) => {{
use $crate::errors::Erroring;
$crate::errors::Jerror::Vme(format!("{}: {}", $crate::errors::vme::VMErr::$kind.err(), format_args!($($args)*)))
}};
}

#[cfg(test)]
mod test {
use crate::errors::Erroring;

const ARM: usize = 0xdeadbeef;

#[test]
fn vme_macro_arm1() {
let control = super::super::Jerror::Vme(format!(
"{}: {}",
super::VMErr::WriteOutOfBounds.err(),
"testing 123"
));
let test = vme!(WriteOutOfBounds, "testing 123");
assert_eq!(control, test)
}

#[test]
fn vme_macro_arm1_2() {
let control = super::super::Jerror::Vme(format!(
"{}: {} {}",
super::VMErr::WriteOutOfBounds.err(),
"testing 123",
ARM
));
let test = vme!(WriteOutOfBounds, "testing 123 {}", ARM);
assert_eq!(control, test)
}

#[test]
fn vme_macro_arm2() {
let test = super::super::Jerror::Vme(format!(
"{}: {}",
super::VMErr::WriteOutOfBounds.err(),
"testing 123"
));
let test = vme!(test, MemReadFail, "123");

let control = super::super::Jerror::Vme(format!(
"{}: {}: {}: {}",
super::VMErr::WriteOutOfBounds.err(),
"testing 123",
super::VMErr::MemReadFail,
"123"
));

assert_eq!(test, control)
}

#[test]
fn vme_macro_arm2_2() {
let test = super::super::Jerror::Vme(format!(
"{}: {}",
super::VMErr::WriteOutOfBounds.err(),
"testing 123",
));
let test = vme!(test, MemReadFail, "123 {}", ARM);

let control = super::super::Jerror::Vme(format!(
"{}: {}: {}: {} {}",
super::VMErr::WriteOutOfBounds.err(),
"testing 123",
super::VMErr::MemReadFail,
"123",
ARM
));

assert_eq!(test, control)
}
}
6 changes: 6 additions & 0 deletions jnd/src/interrupts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use crate::{vm::Machine, Res};

pub fn halt(vm: &mut Machine) -> Res<()> {
vm.state = false;
Ok(())
}
9 changes: 9 additions & 0 deletions jnd/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub mod disassembler;
pub mod errors;
pub mod interrupts;
pub mod mem;
pub mod op;
pub mod reg;
pub mod vm;

pub type Res<T> = Result<T, errors::Jerror>;
31 changes: 31 additions & 0 deletions jnd/src/mem/linear.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use super::Addressable;
use crate::{vme, Res};

#[derive(Debug)]
pub struct LinearMemory {
bytes: Vec<u8>,
}

impl LinearMemory {
pub fn new(n: usize) -> Self {
Self {
bytes: vec![0u8; n],
}
}
}

impl Addressable for LinearMemory {
fn read(&self, addr: u16) -> Option<u8> {
self.bytes.get(addr as usize).copied()
}

fn write(&mut self, addr: u16, value: u8) -> Res<()> {
let addr = addr as usize;
if addr > self.bytes.len() {
return Err(vme!(WriteOutOfBounds, "addr: 0x{addr:X} - values: {value}"));
}

self.bytes[addr] = value;
Ok(())
}
}
34 changes: 34 additions & 0 deletions jnd/src/mem/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
pub mod linear;

use crate::Res;

pub trait Addressable {
fn read(&self, addr: u16) -> Option<u8>;
fn write(&mut self, addr: u16, value: u8) -> Res<()>;

fn read_u16(&self, addr: u16) -> Option<u16> {
if let Some(x0) = self.read(addr) {
if let Some(x1) = self.read(addr + 1) {
return Some(x0 as u16 | ((x1 as u16) << 8));
}
}
None
}

fn write_u16(&mut self, addr: u16, value: u16) -> Res<()> {
let lower = value & 0xff;
let upper = (value & 0xff00) >> 8;
self.write(addr, lower as u8)?;
self.write(addr + 1, upper as u8)
}

fn copy(&mut self, from: u16, to: u16, n: usize) -> Res<()> {
for i in 0..n {
let i = i as u16;
if let Some(x) = self.read(from + i) {
self.write(to + i, x)?;
}
}
Ok(())
}
}
Loading

0 comments on commit 41cf5a4

Please sign in to comment.