progress: new assembler works, instruction set fully implemented with call/ret and push/pop, bf.dsa works which means the dsa assembly language works reliably. still a few bugs to fix. might be able to squeeze out a tiny bit more performance
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
use clap::Parser;
|
||||
use common::{instructions::Instruction, register::Register};
|
||||
use dsa::{
|
||||
BulkAllocStore, Emulator, Page, RandomAccessMemory, SharedState,
|
||||
args::DsaArgs,
|
||||
io::display::{DisplayDevice, DisplayHandle},
|
||||
};
|
||||
use std::{
|
||||
os::unix::thread::JoinHandleExt,
|
||||
process::exit,
|
||||
sync::{Arc, atomic::Ordering},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let args = DsaArgs::parse();
|
||||
|
||||
let mmap = args.get_memory_map();
|
||||
let iomap = args.get_io_map();
|
||||
|
||||
let store = BulkAllocStore::new();
|
||||
let (display, handle) = DisplayDevice::new(80, 25);
|
||||
|
||||
let mut emulator = Emulator::new(store)
|
||||
.with_device(display)
|
||||
.apply_memory_map(mmap)
|
||||
.apply_io_map(iomap)
|
||||
.unwrap();
|
||||
|
||||
if let Some(bin) = args.get_binary() {
|
||||
for (i, ch) in bin.chunks(4).enumerate() {
|
||||
let instruction = Instruction(u32::from_le_bytes(ch.try_into().unwrap()));
|
||||
let hex = ch
|
||||
.iter()
|
||||
.map(|b| format!("{:02X}", b))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
let chars = ch
|
||||
.iter()
|
||||
.map(|b| {
|
||||
if b.is_ascii_graphic() {
|
||||
*b as char
|
||||
} else {
|
||||
'.'
|
||||
}
|
||||
})
|
||||
.collect::<String>();
|
||||
println!("{:04X}: {:<12} {:4} {:?}", i * 4, hex, chars, instruction);
|
||||
}
|
||||
|
||||
let program: Vec<Page> = Page::paginate(&bin).collect();
|
||||
|
||||
for (i, page) in program.iter().enumerate() {
|
||||
emulator.memory_mut().write_page(i as u32 * 4096, &page);
|
||||
}
|
||||
}
|
||||
|
||||
let state = emulator.state_handle();
|
||||
|
||||
const STACK_SIZE: usize = 1024 * 1024 * 16;
|
||||
let runner = thread::Builder::new()
|
||||
.stack_size(STACK_SIZE)
|
||||
.spawn(move || emulator.run().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let observer = thread::spawn(|| observe(state, handle));
|
||||
|
||||
runner.join().unwrap();
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
|
||||
// yeah we don't need this tbh.
|
||||
// observer.join().unwrap();
|
||||
}
|
||||
|
||||
/// todo: remove this!
|
||||
fn observe(state: Arc<SharedState>, handle: DisplayHandle) {
|
||||
loop {
|
||||
state.update_req.store(true, Ordering::Relaxed);
|
||||
thread::sleep(std::time::Duration::from_millis(20));
|
||||
let state = state.proc.load();
|
||||
// println!(
|
||||
// "clock: {}, GP Registers: {:?}",
|
||||
// state.clock, state.registers
|
||||
// );
|
||||
|
||||
if handle.is_dirty() {
|
||||
for line in handle.read_all().chunks(80) {
|
||||
for (i, byte) in line.iter().enumerate() {
|
||||
print!("{}", *byte as char);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user