mirror of
https://github.com/transistorfet/moa.git
synced 2025-03-03 02:29:29 +00:00
Switched to using Rc<RefCell<Box<dyn Trait>>> for devices
This commit is contained in:
parent
e186637f49
commit
73d11ddb79
@ -1,7 +1,7 @@
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::system::System;
|
||||
use crate::memory::Address;
|
||||
use crate::memory::{Address, Addressable};
|
||||
|
||||
use super::execute::{MC68010};
|
||||
|
||||
@ -108,15 +108,15 @@ impl MC68010 {
|
||||
if args.len() > 1 {
|
||||
let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?;
|
||||
let len = if args.len() > 2 { u32::from_str_radix(args[2], 16).map_err(|_| Error::new("Unable to parse length"))? } else { 0x20 };
|
||||
system.dump_memory(addr as Address, len as Address);
|
||||
system.get_bus().dump_memory(addr as Address, len as Address);
|
||||
} else {
|
||||
system.dump_memory(self.state.msp as Address, 0x40 as Address);
|
||||
system.get_bus().dump_memory(self.state.msp as Address, 0x40 as Address);
|
||||
}
|
||||
},
|
||||
"ds" | "stack" | "dumpstack" => {
|
||||
println!("Stack:");
|
||||
for addr in &self.debugger.stack_tracer.calls {
|
||||
println!(" {:08x}", system.read_beu32(*addr as Address)?);
|
||||
println!(" {:08x}", system.get_bus().read_beu32(*addr as Address)?);
|
||||
}
|
||||
},
|
||||
"so" | "stepout" => {
|
||||
|
@ -2,8 +2,8 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::memory::Address;
|
||||
use crate::system::{System, DeviceRefMut};
|
||||
use crate::memory::{Address, Addressable};
|
||||
use crate::system::{System, AddressableDeviceRefMut};
|
||||
|
||||
use super::execute::ERR_ILLEGAL_INSTRUCTION;
|
||||
|
||||
@ -200,13 +200,13 @@ impl M68kDecoder {
|
||||
}
|
||||
|
||||
pub fn decode_at(system: &System, start: u32) -> Result<M68kDecoder, Error> {
|
||||
let (mut memory, relative_addr) = system.get_device_in_range(start as Address, 12)?;
|
||||
let (mut memory, relative_addr) = system.get_bus().get_device_at(start as Address, 12)?;
|
||||
let mut decoder = M68kDecoder::new(start - relative_addr as u32, start);
|
||||
decoder.instruction = decoder.decode_one(&mut memory)?;
|
||||
decoder.instruction = decoder.decode_one(&mut memory.borrow_mut())?;
|
||||
Ok(decoder)
|
||||
}
|
||||
|
||||
pub fn decode_one(&mut self, system: &mut DeviceRefMut<'_>) -> Result<Instruction, Error> {
|
||||
pub fn decode_one(&mut self, system: &mut AddressableDeviceRefMut<'_>) -> Result<Instruction, Error> {
|
||||
let ins = self.read_instruction_word(system)?;
|
||||
|
||||
match ((ins & 0xF000) >> 12) as u8 {
|
||||
@ -609,27 +609,27 @@ impl M68kDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_instruction_word(&mut self, system: &mut DeviceRefMut<'_>) -> Result<u16, Error> {
|
||||
let word = system.read_beu16((self.end - self.base) as Address)?;
|
||||
fn read_instruction_word(&mut self, device: &mut AddressableDeviceRefMut<'_>) -> Result<u16, Error> {
|
||||
let word = device.read_beu16((self.end - self.base) as Address)?;
|
||||
//debug!("{:#010x} {:#06x?}", self.end, word);
|
||||
self.end += 2;
|
||||
Ok(word)
|
||||
}
|
||||
|
||||
fn read_instruction_long(&mut self, system: &mut DeviceRefMut<'_>) -> Result<u32, Error> {
|
||||
let word = system.read_beu32((self.end - self.base) as Address)?;
|
||||
fn read_instruction_long(&mut self, device: &mut AddressableDeviceRefMut<'_>) -> Result<u32, Error> {
|
||||
let word = device.read_beu32((self.end - self.base) as Address)?;
|
||||
//debug!("{:#010x} {:#010x}", self.end, word);
|
||||
self.end += 4;
|
||||
Ok(word)
|
||||
}
|
||||
|
||||
fn decode_lower_effective_address(&mut self, system: &mut DeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
|
||||
fn decode_lower_effective_address(&mut self, system: &mut AddressableDeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
|
||||
let reg = get_low_reg(ins);
|
||||
let mode = get_low_mode(ins);
|
||||
self.get_mode_as_target(system, mode, reg, size)
|
||||
}
|
||||
|
||||
fn decode_upper_effective_address(&mut self, system: &mut DeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
|
||||
fn decode_upper_effective_address(&mut self, system: &mut AddressableDeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
|
||||
let reg = get_high_reg(ins);
|
||||
let mode = get_high_mode(ins);
|
||||
self.get_mode_as_target(system, mode, reg, size)
|
||||
@ -645,7 +645,7 @@ impl M68kDecoder {
|
||||
(rtype, xreg, data, size)
|
||||
}
|
||||
|
||||
pub fn get_mode_as_target(&mut self, system: &mut DeviceRefMut<'_>, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
|
||||
pub fn get_mode_as_target(&mut self, system: &mut AddressableDeviceRefMut<'_>, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
|
||||
let value = match mode {
|
||||
0b000 => Target::DirectDReg(reg),
|
||||
0b001 => Target::DirectAReg(reg),
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::timers::CpuTimer;
|
||||
use crate::memory::Address;
|
||||
use crate::memory::{Address, Addressable};
|
||||
use crate::system::System;
|
||||
|
||||
use super::debugger::M68kDebugger;
|
||||
@ -103,7 +103,7 @@ impl MC68010 {
|
||||
|
||||
println!("Current Instruction: {:#010x} {:?}", self.decoder.start, self.decoder.instruction);
|
||||
println!("");
|
||||
system.dump_memory(self.state.msp as Address, 0x40);
|
||||
system.get_bus().dump_memory(self.state.msp as Address, 0x40);
|
||||
println!("");
|
||||
}
|
||||
|
||||
@ -120,8 +120,8 @@ impl MC68010 {
|
||||
pub fn init(&mut self, system: &System) -> Result<(), Error> {
|
||||
println!("Initializing CPU");
|
||||
|
||||
self.state.msp = system.read_beu32(0)?;
|
||||
self.state.pc = system.read_beu32(4)?;
|
||||
self.state.msp = system.get_bus().read_beu32(0)?;
|
||||
self.state.pc = system.get_bus().read_beu32(4)?;
|
||||
self.state.status = Status::Running;
|
||||
|
||||
Ok(())
|
||||
@ -153,7 +153,7 @@ impl MC68010 {
|
||||
self.push_word(system, self.state.sr)?;
|
||||
self.state.sr |= FLAGS_SUPERVISOR;
|
||||
self.state.sr &= !FLAGS_TRACING;
|
||||
self.state.pc = system.read_beu32((self.state.vbr + offset as u32) as Address)?;
|
||||
self.state.pc = system.get_bus().read_beu32((self.state.vbr + offset as u32) as Address)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -168,7 +168,7 @@ impl MC68010 {
|
||||
// Print instruction bytes for debugging
|
||||
let ins_data: Result<String, Error> =
|
||||
(0..((self.decoder.end - self.decoder.start) / 2)).map(|offset|
|
||||
Ok(format!("{:04x} ", system.read_beu16((self.decoder.start + (offset * 2)) as Address)?))
|
||||
Ok(format!("{:04x} ", system.get_bus().read_beu16((self.decoder.start + (offset * 2)) as Address)?))
|
||||
).collect();
|
||||
debug!("{:#010x}: {}\n\t{:?}\n", self.decoder.start, ins_data?, self.decoder.instruction);
|
||||
}
|
||||
@ -591,12 +591,12 @@ impl MC68010 {
|
||||
fn push_word(&mut self, system: &System, value: u16) -> Result<(), Error> {
|
||||
let reg = self.get_stack_pointer_mut();
|
||||
*reg -= 2;
|
||||
system.write_beu16(*reg as Address, value)
|
||||
system.get_bus().write_beu16(*reg as Address, value)
|
||||
}
|
||||
|
||||
fn pop_word(&mut self, system: &System) -> Result<u16, Error> {
|
||||
let reg = self.get_stack_pointer_mut();
|
||||
let value = system.read_beu16(*reg as Address)?;
|
||||
let value = system.get_bus().read_beu16(*reg as Address)?;
|
||||
*reg += 2;
|
||||
Ok(value)
|
||||
}
|
||||
@ -604,12 +604,12 @@ impl MC68010 {
|
||||
fn push_long(&mut self, system: &System, value: u32) -> Result<(), Error> {
|
||||
let reg = self.get_stack_pointer_mut();
|
||||
*reg -= 4;
|
||||
system.write_beu32(*reg as Address, value)
|
||||
system.get_bus().write_beu32(*reg as Address, value)
|
||||
}
|
||||
|
||||
fn pop_long(&mut self, system: &System) -> Result<u32, Error> {
|
||||
let reg = self.get_stack_pointer_mut();
|
||||
let value = system.read_beu32(*reg as Address)?;
|
||||
let value = system.get_bus().read_beu32(*reg as Address)?;
|
||||
*reg += 4;
|
||||
Ok(value)
|
||||
}
|
||||
@ -902,9 +902,9 @@ fn get_value_sized(value: u32, size: Size) -> u32 {
|
||||
|
||||
fn get_address_sized(system: &System, addr: Address, size: Size) -> Result<u32, Error> {
|
||||
match size {
|
||||
Size::Byte => system.read_u8(addr).map(|value| value as u32),
|
||||
Size::Word => system.read_beu16(addr).map(|value| value as u32),
|
||||
Size::Long => system.read_beu32(addr),
|
||||
Size::Byte => system.get_bus().read_u8(addr).map(|value| value as u32),
|
||||
Size::Word => system.get_bus().read_beu16(addr).map(|value| value as u32),
|
||||
Size::Long => system.get_bus().read_beu32(addr),
|
||||
}
|
||||
}
|
||||
|
||||
@ -918,9 +918,9 @@ fn set_value_sized(addr: &mut u32, value: u32, size: Size) {
|
||||
|
||||
fn set_address_sized(system: &System, addr: Address, value: u32, size: Size) -> Result<(), Error> {
|
||||
match size {
|
||||
Size::Byte => system.write_u8(addr, value as u8),
|
||||
Size::Word => system.write_beu16(addr, value as u16),
|
||||
Size::Long => system.write_beu32(addr, value),
|
||||
Size::Byte => system.get_bus().write_u8(addr, value as u8),
|
||||
Size::Word => system.get_bus().write_beu16(addr, value as u16),
|
||||
Size::Long => system.get_bus().write_beu32(addr, value),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
use crate::memory::{Address, MemoryBlock};
|
||||
use crate::system::System;
|
||||
use crate::memory::{Address, Addressable, MemoryBlock};
|
||||
use crate::system::{System, wrap_addressable};
|
||||
|
||||
use super::execute::MC68010;
|
||||
use super::decode::Instruction;
|
||||
@ -14,9 +14,9 @@ fn init_test() -> (MC68010, System) {
|
||||
// Insert basic initialization
|
||||
let data = vec![0; 0x00100000];
|
||||
let mem = MemoryBlock::new(data);
|
||||
system.add_device(0x00000000, Box::new(mem)).unwrap();
|
||||
system.write_beu32(0, INIT_STACK as u32).unwrap();
|
||||
system.write_beu32(4, INIT_ADDR as u32).unwrap();
|
||||
system.add_addressable_device(0x00000000, wrap_addressable(mem)).unwrap();
|
||||
system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap();
|
||||
system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap();
|
||||
|
||||
let mut cpu = MC68010::new();
|
||||
cpu.step(&system).unwrap();
|
||||
@ -36,7 +36,7 @@ mod tests {
|
||||
fn instruction_nop() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0x4e71).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0x4e71).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
|
||||
cpu.execute_current(&system).unwrap();
|
||||
@ -48,8 +48,8 @@ mod tests {
|
||||
fn instruction_ori() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0x0008).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0x0008).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::OR(Target::Immediate(0xFF), Target::DirectAReg(0), Size::Byte));
|
||||
cpu.execute_current(&system).unwrap();
|
||||
@ -60,9 +60,9 @@ mod tests {
|
||||
fn instruction_cmpi_equal() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 4, 0x0020).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0020).unwrap();
|
||||
cpu.step(&system).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x20), Target::DirectDReg(0), Size::Byte));
|
||||
@ -74,9 +74,9 @@ mod tests {
|
||||
fn instruction_cmpi_greater() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 4, 0x0030).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0030).unwrap();
|
||||
cpu.step(&system).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte));
|
||||
@ -88,9 +88,9 @@ mod tests {
|
||||
fn instruction_cmpi_less() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 4, 0x0010).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0010).unwrap();
|
||||
cpu.step(&system).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x10), Target::DirectDReg(0), Size::Byte));
|
||||
@ -102,8 +102,8 @@ mod tests {
|
||||
fn instruction_andi_sr() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0x027C).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0x027C).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoSR(0xF8FF));
|
||||
//cpu.execute_current(&system).unwrap();
|
||||
@ -114,8 +114,8 @@ mod tests {
|
||||
fn instruction_muls() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0xC1FC).unwrap();
|
||||
system.write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0xC1FC).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed));
|
||||
//cpu.execute_current(&system).unwrap();
|
||||
@ -126,7 +126,7 @@ mod tests {
|
||||
fn instruction_asli() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0xE300).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0xE300).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
|
||||
|
||||
@ -140,7 +140,7 @@ mod tests {
|
||||
fn instruction_asri() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0xE200).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0xE200).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
|
||||
|
||||
@ -154,7 +154,7 @@ mod tests {
|
||||
fn instruction_roli() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0xE318).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0xE318).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
|
||||
|
||||
@ -168,7 +168,7 @@ mod tests {
|
||||
fn instruction_rori() {
|
||||
let (mut cpu, mut system) = init_test();
|
||||
|
||||
system.write_beu16(INIT_ADDR, 0xE218).unwrap();
|
||||
system.get_bus().write_beu16(INIT_ADDR, 0xE218).unwrap();
|
||||
cpu.decode_next(&system).unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
|
||||
|
||||
@ -220,7 +220,7 @@ mod tests {
|
||||
let expected_addr = INIT_ADDR;
|
||||
let expected = 0x12345678;
|
||||
|
||||
system.write_beu32(INIT_ADDR, expected).unwrap();
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
let target = cpu.decoder.get_mode_as_target(&system, 0b010, 0b010, Some(size)).unwrap();
|
||||
assert_eq!(target, Target::IndirectAReg(2));
|
||||
|
||||
@ -237,7 +237,7 @@ mod tests {
|
||||
let expected_addr = INIT_ADDR;
|
||||
let expected = 0x12345678;
|
||||
|
||||
system.write_beu32(INIT_ADDR, expected).unwrap();
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
let target = cpu.decoder.get_mode_as_target(&system, 0b011, 0b010, Some(size)).unwrap();
|
||||
assert_eq!(target, Target::IndirectARegInc(2));
|
||||
|
||||
@ -255,7 +255,7 @@ mod tests {
|
||||
let expected_addr = INIT_ADDR + 4;
|
||||
let expected = 0x12345678;
|
||||
|
||||
system.write_beu32(INIT_ADDR, expected).unwrap();
|
||||
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
|
||||
let target = cpu.decoder.get_mode_as_target(&system, 0b100, 0b010, Some(size)).unwrap();
|
||||
assert_eq!(target, Target::IndirectARegDec(2));
|
||||
|
||||
@ -273,7 +273,7 @@ mod tests {
|
||||
let size = Size::Word;
|
||||
let expected = 0x1234;
|
||||
|
||||
system.write_beu16(cpu.decoder.end as Address, expected as u16).unwrap();
|
||||
system.get_bus().write_beu16(cpu.decoder.end as Address, expected as u16).unwrap();
|
||||
let target = cpu.decoder.get_mode_as_target(&system, 0b111, 0b100, Some(size)).unwrap();
|
||||
assert_eq!(target, Target::Immediate(expected));
|
||||
|
||||
|
10
src/main.rs
10
src/main.rs
@ -11,7 +11,7 @@ use crate::memory::MemoryBlock;
|
||||
use crate::cpus::m68k::MC68010;
|
||||
use crate::peripherals::ata::AtaDevice;
|
||||
use crate::peripherals::mc68681::MC68681;
|
||||
use crate::system::{System};
|
||||
use crate::system::{System, wrap_addressable};
|
||||
|
||||
fn main() {
|
||||
let mut system = System::new();
|
||||
@ -20,19 +20,19 @@ fn main() {
|
||||
for byte in monitor.contents.iter() {
|
||||
print!("{:02x} ", byte);
|
||||
}
|
||||
system.add_device(0x00000000, Box::new(monitor)).unwrap();
|
||||
system.add_addressable_device(0x00000000, wrap_addressable(monitor)).unwrap();
|
||||
|
||||
let mut ram = MemoryBlock::new(vec![0; 0x00100000]);
|
||||
ram.load_at(0, "binaries/kernel.bin").unwrap();
|
||||
system.add_device(0x00100000, Box::new(ram)).unwrap();
|
||||
system.add_addressable_device(0x00100000, wrap_addressable(ram)).unwrap();
|
||||
|
||||
let mut ata = AtaDevice::new();
|
||||
ata.load("binaries/disk-with-partition-table.img").unwrap();
|
||||
system.add_device(0x00600000, Box::new(ata)).unwrap();
|
||||
system.add_addressable_device(0x00600000, wrap_addressable(ata)).unwrap();
|
||||
|
||||
let mut serial = MC68681::new();
|
||||
serial.open().unwrap();
|
||||
system.add_device(0x00700000, Box::new(serial)).unwrap();
|
||||
system.add_addressable_device(0x00700000, wrap_addressable(serial)).unwrap();
|
||||
|
||||
|
||||
let mut cpu = MC68010::new();
|
||||
|
@ -2,7 +2,7 @@
|
||||
use std::fs;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::system::{Clock, DeviceNumber, Device, System};
|
||||
use crate::system::{Clock, DeviceNumber, Steppable, AddressableDeviceBox, System};
|
||||
|
||||
|
||||
pub type Address = u64;
|
||||
@ -91,7 +91,7 @@ impl Addressable for MemoryBlock {
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for MemoryBlock {
|
||||
impl Steppable for MemoryBlock {
|
||||
fn step(&mut self, _system: &System) -> Result<Clock, Error> {
|
||||
Ok(1)
|
||||
}
|
||||
@ -101,7 +101,7 @@ impl Device for MemoryBlock {
|
||||
pub struct Block {
|
||||
pub base: Address,
|
||||
pub length: usize,
|
||||
pub dev: DeviceNumber,
|
||||
pub dev: AddressableDeviceBox,
|
||||
}
|
||||
|
||||
pub struct Bus {
|
||||
@ -115,7 +115,7 @@ impl Bus {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, base: Address, length: usize, dev: DeviceNumber) {
|
||||
pub fn insert(&mut self, base: Address, length: usize, dev: AddressableDeviceBox) {
|
||||
let block = Block { base, length, dev };
|
||||
for i in 0..self.blocks.len() {
|
||||
if self.blocks[i].base > block.base {
|
||||
@ -126,12 +126,12 @@ impl Bus {
|
||||
self.blocks.insert(0, block);
|
||||
}
|
||||
|
||||
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(DeviceNumber, Address), Error> {
|
||||
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(AddressableDeviceBox, Address), Error> {
|
||||
for block in &self.blocks {
|
||||
if addr >= block.base && addr <= (block.base + block.length as Address) {
|
||||
let relative_addr = addr - block.base;
|
||||
if relative_addr as usize + count <= block.length {
|
||||
return Ok((block.dev, relative_addr));
|
||||
return Ok((block.dev.clone(), relative_addr));
|
||||
} else {
|
||||
return Err(Error::new(&format!("Error reading address {:#010x}", addr)));
|
||||
}
|
||||
@ -140,9 +140,42 @@ impl Bus {
|
||||
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
|
||||
}
|
||||
|
||||
pub fn max_address(&self) -> Address {
|
||||
pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) {
|
||||
while count > 0 {
|
||||
let mut line = format!("{:#010x}: ", addr);
|
||||
|
||||
let to = if count < 16 { count / 2 } else { 8 };
|
||||
for _ in 0..to {
|
||||
let word = self.read_beu16(addr);
|
||||
if word.is_err() {
|
||||
println!("{}", line);
|
||||
return;
|
||||
}
|
||||
line += &format!("{:#06x} ", word.unwrap());
|
||||
addr += 2;
|
||||
count -= 2;
|
||||
}
|
||||
println!("{}", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Addressable for Bus {
|
||||
fn len(&self) -> usize {
|
||||
let block = &self.blocks[self.blocks.len() - 1];
|
||||
block.base + block.length as Address
|
||||
(block.base as usize) + block.length
|
||||
}
|
||||
|
||||
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
|
||||
let (dev, relative_addr) = self.get_device_at(addr, count)?;
|
||||
let result = dev.borrow_mut().read(relative_addr, count);
|
||||
result
|
||||
}
|
||||
|
||||
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
||||
let (dev, relative_addr) = self.get_device_at(addr, data.len())?;
|
||||
let result = dev.borrow_mut().write(relative_addr, data);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use std::fs;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::memory::{Address, Addressable};
|
||||
use crate::system::{Clock, Device, System};
|
||||
use crate::system::{Clock, Steppable, System};
|
||||
|
||||
|
||||
const ATA_REG_DEV_CONTROL: Address = 0x1D;
|
||||
@ -120,7 +120,7 @@ println!(">> {:x}", data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for AtaDevice {
|
||||
impl Steppable for AtaDevice {
|
||||
fn step(&mut self, _system: &System) -> Result<Clock, Error> {
|
||||
Ok(1)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use nix::unistd::sleep;
|
||||
use nix::fcntl::{fcntl, FcntlArg};
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::system::{Clock, Device, System};
|
||||
use crate::system::{Clock, Steppable, System};
|
||||
use crate::memory::{Address, Addressable};
|
||||
|
||||
|
||||
@ -147,7 +147,7 @@ impl Addressable for MC68681 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for MC68681 {
|
||||
impl Steppable for MC68681 {
|
||||
fn step(&mut self, system: &System) -> Result<Clock, Error> {
|
||||
self.step_internal(system)?;
|
||||
Ok(1)
|
||||
|
109
src/system.rs
109
src/system.rs
@ -1,4 +1,5 @@
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
|
||||
use crate::error::Error;
|
||||
@ -8,109 +9,63 @@ use crate::memory::{self, Address, Addressable, Bus};
|
||||
pub type Clock = u64;
|
||||
pub type DeviceNumber = u8;
|
||||
|
||||
pub type DeviceRefMut<'a> = RefMut<'a, Box<dyn AddressableDevice>>;
|
||||
|
||||
pub trait Device: Addressable {
|
||||
pub trait Steppable {
|
||||
fn step(&mut self, system: &System) -> Result<Clock, Error>;
|
||||
}
|
||||
|
||||
pub trait AddressableDevice: Device + Addressable { }
|
||||
pub trait Interruptable {
|
||||
fn handle_interrupt(&mut self, system: &System, number: u8) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
impl<T: Device + Addressable> AddressableDevice for T { }
|
||||
pub trait AddressableDevice: Addressable + Steppable { }
|
||||
pub trait InterruptableDevice: Interruptable + Steppable { }
|
||||
|
||||
impl<T: Addressable + Steppable> AddressableDevice for T { }
|
||||
impl<T: Interruptable + Steppable> InterruptableDevice for T { }
|
||||
|
||||
pub type AddressableDeviceBox = Rc<RefCell<Box<dyn AddressableDevice>>>;
|
||||
pub type InterruptableDeviceBox = Rc<RefCell<Box<dyn InterruptableDevice>>>;
|
||||
|
||||
pub type AddressableDeviceRefMut<'a> = RefMut<'a, Box<dyn AddressableDevice>>;
|
||||
|
||||
pub fn wrap_addressable<T: AddressableDevice + 'static>(value: T) -> AddressableDeviceBox {
|
||||
Rc::new(RefCell::new(Box::new(value)))
|
||||
}
|
||||
|
||||
|
||||
pub struct System {
|
||||
pub clock: Clock,
|
||||
pub devices: Vec<RefCell<Box<dyn AddressableDevice>>>,
|
||||
pub bus: Bus,
|
||||
pub addressable_devices: Vec<AddressableDeviceBox>,
|
||||
pub bus: RefCell<Bus>,
|
||||
}
|
||||
|
||||
impl System {
|
||||
pub fn new() -> System {
|
||||
System {
|
||||
clock: 0,
|
||||
devices: vec![],
|
||||
bus: Bus::new(),
|
||||
addressable_devices: vec![],
|
||||
bus: RefCell::new(Bus::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_device(&mut self, addr: Address, device: Box<dyn AddressableDevice>) -> Result<(), Error> {
|
||||
self.bus.insert(addr, device.len(), self.devices.len() as DeviceNumber);
|
||||
self.devices.push(RefCell::new(device));
|
||||
pub fn get_bus(&self) -> RefMut<'_, Bus> {
|
||||
self.bus.borrow_mut()
|
||||
}
|
||||
|
||||
pub fn add_addressable_device(&mut self, addr: Address, device: AddressableDeviceBox) -> Result<(), Error> {
|
||||
let length = device.borrow().len();
|
||||
self.bus.borrow_mut().insert(addr, length, device.clone());
|
||||
self.addressable_devices.push(device);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn step(&mut self) -> Result<(), Error> {
|
||||
self.clock += 1;
|
||||
for dev in &self.devices {
|
||||
for dev in &self.addressable_devices {
|
||||
dev.borrow_mut().step(&self)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_device_in_range(&self, addr: Address, count: usize) -> Result<(DeviceRefMut<'_>, Address), Error> {
|
||||
let (dev, relative_addr) = self.bus.get_device_at(addr, count)?;
|
||||
Ok((self.devices[dev as usize].borrow_mut(), relative_addr))
|
||||
}
|
||||
|
||||
|
||||
pub fn read(&self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
|
||||
let (dev, relative_addr) = self.bus.get_device_at(addr, count)?;
|
||||
self.devices[dev as usize].borrow_mut().read(relative_addr, count)
|
||||
}
|
||||
|
||||
pub fn write(&self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
||||
let (dev, relative_addr) = self.bus.get_device_at(addr, data.len())?;
|
||||
self.devices[dev as usize].borrow_mut().write(relative_addr, data)
|
||||
}
|
||||
|
||||
|
||||
pub fn read_u8(&self, addr: Address) -> Result<u8, Error> {
|
||||
Ok(self.read(addr, 1)?[0])
|
||||
}
|
||||
|
||||
pub fn read_beu16(&self, addr: Address) -> Result<u16, Error> {
|
||||
Ok(memory::read_beu16(&self.read(addr, 2)?))
|
||||
}
|
||||
|
||||
pub fn read_beu32(&self, addr: Address) -> Result<u32, Error> {
|
||||
Ok(memory::read_beu32(&self.read(addr, 4)?))
|
||||
}
|
||||
|
||||
pub fn write_u8(&self, addr: Address, value: u8) -> Result<(), Error> {
|
||||
let data = [value];
|
||||
self.write(addr, &data)
|
||||
}
|
||||
|
||||
pub fn write_beu16(&self, addr: Address, value: u16) -> Result<(), Error> {
|
||||
let data = memory::write_beu16(value);
|
||||
self.write(addr, &data)
|
||||
}
|
||||
|
||||
pub fn write_beu32(&self, addr: Address, value: u32) -> Result<(), Error> {
|
||||
let data = memory::write_beu32(value);
|
||||
self.write(addr, &data)
|
||||
}
|
||||
|
||||
|
||||
pub fn dump_memory(&self, mut addr: Address, mut count: Address) {
|
||||
while count > 0 {
|
||||
let mut line = format!("{:#010x}: ", addr);
|
||||
|
||||
let to = if count < 16 { count / 2 } else { 8 };
|
||||
for _ in 0..to {
|
||||
let word = self.read_beu16(addr);
|
||||
if word.is_err() {
|
||||
println!("{}", line);
|
||||
return;
|
||||
}
|
||||
line += &format!("{:#06x} ", word.unwrap());
|
||||
addr += 2;
|
||||
count -= 2;
|
||||
}
|
||||
println!("{}", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
6
todo.txt
6
todo.txt
@ -1,4 +1,10 @@
|
||||
|
||||
* how will you add the cpu, which is not addressable, but is steppable, and also interruptable... what else?
|
||||
* should you simulate bus arbitration?
|
||||
* if the bus had an Rc<RefCell<Box<dyn AddressableDevice>>>, then it could be like AddressSpace used to be, with it's own Addressable, and then you could
|
||||
access one of multiple busses to do an op on it, rather than a single bus per machine
|
||||
* can you get rid of the duplicate read/write functions in System?
|
||||
|
||||
* how do you pass in a mutable system to a mutable device? At the very least, I need the AddressSpace, but that needs access to the devices/memory segments.
|
||||
I could make System contain refcells for submutability
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user