Compare commits
2 Commits
f0323dab2e
...
3a4d2b0c9d
Author | SHA1 | Date | |
---|---|---|---|
3a4d2b0c9d | |||
5259bbbe3c |
101
src/backplane.rs
101
src/backplane.rs
@ -123,7 +123,7 @@ impl Backplane {
|
||||
card: Rc::clone(&cards[interconnect.a_index]),
|
||||
card_no: interconnect.a_index,
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
@ -134,7 +134,7 @@ impl Backplane {
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
for card in self.cards.iter() {
|
||||
for card in &self.cards {
|
||||
card.borrow_mut().reset();
|
||||
}
|
||||
}
|
||||
@ -148,43 +148,51 @@ impl Backplane {
|
||||
}
|
||||
|
||||
pub fn read_word(&self, address: u32) -> Result<u16, BusError> {
|
||||
self.mem_helper(
|
||||
address,
|
||||
|mut card| card.read_word(address),
|
||||
|mut card| card.read_word_io(address as u8),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
if let Some(mmu) = self.mmu {
|
||||
self.cards[mmu]
|
||||
.borrow_mut()
|
||||
.try_as_mmu()
|
||||
.unwrap()
|
||||
.read_word(address, self)
|
||||
} else {
|
||||
self.read_word_phys(address)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_byte(&self, address: u32) -> Result<u8, BusError> {
|
||||
self.mem_helper(
|
||||
address,
|
||||
|mut card| card.read_byte(address),
|
||||
|mut card| card.read_byte_io(address as u8),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
if let Some(mmu) = self.mmu {
|
||||
self.cards[mmu]
|
||||
.borrow_mut()
|
||||
.try_as_mmu()
|
||||
.unwrap()
|
||||
.read_byte(address, self)
|
||||
} else {
|
||||
self.read_byte_phys(address)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_word(&self, address: u32, data: u16) -> Result<(), BusError> {
|
||||
self.mem_helper(
|
||||
address,
|
||||
|mut card| card.write_word(address, data),
|
||||
|mut card| card.write_word_io(address as u8, data),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
if let Some(mmu) = self.mmu {
|
||||
self.cards[mmu]
|
||||
.borrow_mut()
|
||||
.try_as_mmu()
|
||||
.unwrap()
|
||||
.write_word(address, data, self)
|
||||
} else {
|
||||
self.write_word_phys(address, data)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_byte(&self, address: u32, data: u8) -> Result<(), BusError> {
|
||||
self.mem_helper(
|
||||
address,
|
||||
|mut card| card.write_byte(address, data),
|
||||
|mut card| card.write_byte_io(address as u8, data),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
if let Some(mmu) = self.mmu {
|
||||
self.cards[mmu]
|
||||
.borrow_mut()
|
||||
.try_as_mmu()
|
||||
.unwrap()
|
||||
.write_byte(address, data, self)
|
||||
} else {
|
||||
self.write_byte_phys(address, data)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_word_phys(&self, address: u32) -> Result<u16, BusError> {
|
||||
@ -192,41 +200,30 @@ impl Backplane {
|
||||
address,
|
||||
|mut card| card.read_word(address),
|
||||
|mut card| card.read_word_io(address as u8),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn read_byte_phys(&self, address: u32) -> Result<u8, BusError> {
|
||||
self.mem_helper(
|
||||
address,
|
||||
|mut card| card.read_byte(address),
|
||||
|mut card| card.read_byte_io(address as u8),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn write_word_phys(&self, address: u32, data: u16) -> Result<(), BusError> {
|
||||
self.mem_helper(
|
||||
address,
|
||||
|mut card| card.write_word(address, data),
|
||||
|mut card| card.write_word_io(address as u8, data),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn write_byte_phys(&self, address: u32, data: u8) -> Result<(), BusError> {
|
||||
self.mem_helper(
|
||||
address,
|
||||
|mut card| card.write_byte(address, data),
|
||||
|mut card| card.write_byte_io(address as u8, data),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
@ -235,29 +232,11 @@ impl Backplane {
|
||||
address: u32,
|
||||
mut mem_func: M,
|
||||
mut io_func: I,
|
||||
bypass_mmu: bool,
|
||||
write: bool,
|
||||
) -> Result<T, BusError>
|
||||
where
|
||||
M: FnMut(RefMut<'_, dyn Card>) -> NullableResult<T, BusError>,
|
||||
I: FnMut(RefMut<'_, dyn Card>) -> NullableResult<T, BusError>,
|
||||
{
|
||||
let address = if bypass_mmu {
|
||||
address
|
||||
} else if let Some(card_no) = self.mmu {
|
||||
match self.cards[card_no]
|
||||
.borrow_mut()
|
||||
.try_as_mmu()
|
||||
.unwrap()
|
||||
.translate_address(self, address, write)
|
||||
{
|
||||
NullableResult::Ok(address) => address,
|
||||
NullableResult::Err(e) => return Err(e),
|
||||
NullableResult::Null => return Err(BusError),
|
||||
}
|
||||
} else {
|
||||
address
|
||||
};
|
||||
let res = match address {
|
||||
(0..=0x00fe_ffff) | (0x0100_0000..=0xffff_ffff) => self
|
||||
.cards
|
||||
@ -282,9 +261,9 @@ impl Backplane {
|
||||
fn handle_dma(&self) {
|
||||
if !self.in_dma.get() {
|
||||
self.in_dma.set(true);
|
||||
for card in self.cards.iter() {
|
||||
for card in &self.cards {
|
||||
if let Ok(mut card) = card.try_borrow_mut() {
|
||||
card.handle_dma(self)
|
||||
card.handle_dma(self);
|
||||
}
|
||||
}
|
||||
self.in_dma.set(false);
|
||||
|
26
src/card.rs
26
src/card.rs
@ -120,7 +120,7 @@ pub trait Card: Debug + Display + mopa::Any {
|
||||
|
||||
fn handle_dma(&mut self, _backplane: &Backplane) {}
|
||||
|
||||
fn try_as_mmu(&mut self) -> Option<&mut dyn MMU> {
|
||||
fn try_as_mmu(&mut self) -> Option<&mut dyn Mmu> {
|
||||
None
|
||||
}
|
||||
|
||||
@ -138,17 +138,23 @@ pub trait Card: Debug + Display + mopa::Any {
|
||||
fn handle_interconnect_message(&mut self, _interconnect_no: usize, _message: Box<dyn Any>) {}
|
||||
}
|
||||
|
||||
pub trait MMU: Card {
|
||||
fn translate_address(
|
||||
&mut self,
|
||||
backplane: &Backplane,
|
||||
address: u32,
|
||||
write: bool,
|
||||
) -> NullableResult<u32, BusError>;
|
||||
}
|
||||
|
||||
mopafy!(Card);
|
||||
|
||||
pub trait Mmu: Debug {
|
||||
fn read_word(&mut self, address: u32, backplane: &Backplane) -> Result<u16, BusError>;
|
||||
fn read_byte(&mut self, address: u32, backplane: &Backplane) -> Result<u8, BusError>;
|
||||
|
||||
fn write_word(
|
||||
&mut self,
|
||||
address: u32,
|
||||
data: u16,
|
||||
backplane: &Backplane,
|
||||
) -> Result<(), BusError>;
|
||||
|
||||
fn write_byte(&mut self, address: u32, data: u8, backplane: &Backplane)
|
||||
-> Result<(), BusError>;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const fn u64_set_be_byte(val: u64, idx: u8, byte: u8) -> u64 {
|
||||
let mut bytes = val.to_be_bytes();
|
||||
|
16
src/main.rs
16
src/main.rs
@ -336,7 +336,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
state.cpu.bus_mut().write_word(address, data)?;
|
||||
} else {
|
||||
let data = parse::<u8>(args.get_one::<String>("data").unwrap())?;
|
||||
state.cpu.bus_mut().write_byte(address, data as u8)?;
|
||||
state.cpu.bus_mut().write_byte(address, data)?;
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
@ -384,7 +384,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
.short('a')
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["delete", "set-active"])
|
||||
.conflicts_with_all(["delete", "set-active"])
|
||||
.help("Append the file's symbols to the loaded list of symbols"),
|
||||
)
|
||||
.arg(
|
||||
@ -393,7 +393,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
.short('d')
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["append", "set-active"])
|
||||
.conflicts_with_all(["append", "set-active"])
|
||||
.help("Delete the symbol table instead of loading it"),
|
||||
)
|
||||
.arg(
|
||||
@ -403,7 +403,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
|
||||
.value_parser(BoolishValueParser::new())
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["append", "delete"])
|
||||
.conflicts_with_all(["append", "delete"])
|
||||
.help("Set whether the symbol table is active or not"),
|
||||
)
|
||||
.about("Load symbols from an ELF file, or list symbols if no file provided"),
|
||||
@ -524,12 +524,12 @@ fn disas_fmt(
|
||||
symbol_tables: &SymbolTables,
|
||||
) -> (String, Result<u32, DisassemblyError<DetailedBusError>>) {
|
||||
let addr_fmt = if let Some((table, symbol, offset)) = symbol_tables.address_to_symbol(addr) {
|
||||
format!("{}:{} + {} (0x{:x})", table, symbol, offset, addr)
|
||||
format!("{table}:{symbol} + {offset} (0x{addr:x})")
|
||||
} else {
|
||||
format!("0x{:x}", addr)
|
||||
format!("0x{addr:x}")
|
||||
};
|
||||
match cpu.disassemble(addr) {
|
||||
Ok((ins, new_addr)) => (format!("{}: {}\n", addr_fmt, ins), Ok(new_addr)),
|
||||
Err(e) => (format!("{}: {}\n", addr_fmt, e), Err(e)),
|
||||
Ok((ins, new_addr)) => (format!("{addr_fmt}: {ins}\n"), Ok(new_addr)),
|
||||
Err(e) => (format!("{addr_fmt}: {e}\n"), Err(e)),
|
||||
}
|
||||
}
|
||||
|
55
src/mmu.rs
55
src/mmu.rs
@ -4,7 +4,7 @@ use nullable_result::NullableResult;
|
||||
|
||||
use crate::{
|
||||
backplane::Backplane,
|
||||
card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card, MMU},
|
||||
card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card, Mmu},
|
||||
m68k::BusError,
|
||||
register,
|
||||
};
|
||||
@ -53,7 +53,7 @@ impl Card for MmuCard {
|
||||
})
|
||||
}
|
||||
|
||||
fn try_as_mmu(&mut self) -> Option<&mut dyn MMU> {
|
||||
fn try_as_mmu(&mut self) -> Option<&mut dyn Mmu> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
@ -173,16 +173,13 @@ impl Display for MmuCard {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Mmu;
|
||||
|
||||
impl MMU for MmuCard {
|
||||
impl MmuCard {
|
||||
fn translate_address(
|
||||
&mut self,
|
||||
backplane: &Backplane,
|
||||
address: u32,
|
||||
backplane: &Backplane,
|
||||
write: bool,
|
||||
) -> NullableResult<u32, BusError> {
|
||||
) -> Result<u32, BusError> {
|
||||
let print_debug = self.print_debug;
|
||||
if self.enabled {
|
||||
let page = address >> 12;
|
||||
@ -200,7 +197,7 @@ impl MMU for MmuCard {
|
||||
if print_debug {
|
||||
println!("No mapping frame for this quarter");
|
||||
}
|
||||
return NullableResult::Null;
|
||||
return Err(BusError);
|
||||
}
|
||||
let map_frame = self.map_frames[(page >> 10) as usize];
|
||||
let entry_address = (map_frame) | ((page & 0x3FF) << 2);
|
||||
@ -221,7 +218,7 @@ impl MMU for MmuCard {
|
||||
if print_debug {
|
||||
println!("Entry not writable");
|
||||
}
|
||||
return NullableResult::Err(BusError);
|
||||
return Err(BusError);
|
||||
}
|
||||
if print_debug {
|
||||
println!(
|
||||
@ -229,17 +226,49 @@ impl MMU for MmuCard {
|
||||
(entry.frame << 12) | offset
|
||||
);
|
||||
}
|
||||
NullableResult::Ok((entry.frame << 12) | offset)
|
||||
Ok((entry.frame << 12) | offset)
|
||||
} else {
|
||||
if print_debug {
|
||||
println!("Entry not present");
|
||||
}
|
||||
NullableResult::Null
|
||||
Err(BusError)
|
||||
}
|
||||
} else {
|
||||
NullableResult::Ok(address)
|
||||
Ok(address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mmu for MmuCard {
|
||||
fn read_word(&mut self, address: u32, backplane: &Backplane) -> Result<u16, BusError> {
|
||||
let address = self.translate_address(address, backplane, false)?;
|
||||
backplane.read_word_phys(address)
|
||||
}
|
||||
|
||||
fn read_byte(&mut self, address: u32, backplane: &Backplane) -> Result<u8, BusError> {
|
||||
let address = self.translate_address(address, backplane, false)?;
|
||||
backplane.read_byte_phys(address)
|
||||
}
|
||||
|
||||
fn write_word(
|
||||
&mut self,
|
||||
address: u32,
|
||||
data: u16,
|
||||
backplane: &Backplane,
|
||||
) -> Result<(), BusError> {
|
||||
let address = self.translate_address(address, backplane, true)?;
|
||||
backplane.write_word_phys(address, data)
|
||||
}
|
||||
|
||||
fn write_byte(
|
||||
&mut self,
|
||||
address: u32,
|
||||
data: u8,
|
||||
backplane: &Backplane,
|
||||
) -> Result<(), BusError> {
|
||||
let address = self.translate_address(address, backplane, true)?;
|
||||
backplane.write_byte_phys(address, data)
|
||||
}
|
||||
}
|
||||
|
||||
register!(MmuCard, "mmu");
|
||||
|
@ -27,8 +27,8 @@ struct Config {
|
||||
|
||||
bitflags! {
|
||||
struct Status: u16 {
|
||||
const BUSY = 0b00000001;
|
||||
const DATA_READY = 0b00000010;
|
||||
const BUSY = 0b000_00001;
|
||||
const DATA_READY = 0b0000_0010;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user