Pass full function code to all memory functions
This commit is contained in:
parent
2447a98e87
commit
40acac97b5
@ -9,6 +9,7 @@ use anyhow::anyhow;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nullable_result::{GeneralIterExt, NullableResult};
|
use nullable_result::{GeneralIterExt, NullableResult};
|
||||||
|
|
||||||
|
use crate::m68k::FunctionCode;
|
||||||
use crate::InterconnectConfig;
|
use crate::InterconnectConfig;
|
||||||
use crate::{
|
use crate::{
|
||||||
card::{self, Card},
|
card::{self, Card},
|
||||||
@ -151,102 +152,102 @@ impl Backplane {
|
|||||||
.cmd(cmd, self)
|
.cmd(cmd, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_word(&self, address: u32, supervisor: bool) -> Result<u16, BusError> {
|
pub fn read_word(&self, address: u32, function: FunctionCode) -> Result<u16, BusError> {
|
||||||
self.mem_helper(
|
self.mem_helper(
|
||||||
address,
|
address,
|
||||||
|address, mut card| card.read_word(address),
|
|address, mut card| card.read_word(address, function),
|
||||||
|address, mut card| card.read_word_io(address as u8),
|
|address, mut card| card.read_word_io(address as u8, function),
|
||||||
|address| self.read_word_io(address as u8),
|
|address| self.read_word_io(address as u8),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
supervisor,
|
function,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_byte(&self, address: u32, supervisor: bool) -> Result<u8, BusError> {
|
pub fn read_byte(&self, address: u32, function: FunctionCode) -> Result<u8, BusError> {
|
||||||
self.mem_helper(
|
self.mem_helper(
|
||||||
address,
|
address,
|
||||||
|address, mut card| card.read_byte(address),
|
|address, mut card| card.read_byte(address, function),
|
||||||
|address, mut card| card.read_byte_io(address as u8),
|
|address, mut card| card.read_byte_io(address as u8, function),
|
||||||
|address| self.read_byte_io(address as u8),
|
|address| self.read_byte_io(address as u8),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
supervisor,
|
function,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_word(&self, address: u32, data: u16, supervisor: bool) -> Result<(), BusError> {
|
pub fn write_word(&self, address: u32, data: u16, function: FunctionCode) -> Result<(), BusError> {
|
||||||
self.mem_helper(
|
self.mem_helper(
|
||||||
address,
|
address,
|
||||||
|address, mut card| card.write_word(address, data),
|
|address, mut card| card.write_word(address, data, function),
|
||||||
|address, mut card| card.write_word_io(address as u8, data),
|
|address, mut card| card.write_word_io(address as u8, data, function),
|
||||||
|address| self.write_word_io(address as u8, data),
|
|address| self.write_word_io(address as u8, data),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
supervisor,
|
function,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_byte(&self, address: u32, data: u8, supervisor: bool) -> Result<(), BusError> {
|
pub fn write_byte(&self, address: u32, data: u8, function: FunctionCode) -> Result<(), BusError> {
|
||||||
self.mem_helper(
|
self.mem_helper(
|
||||||
address,
|
address,
|
||||||
|address, mut card| card.write_byte(address, data),
|
|address, mut card| card.write_byte(address, data, function),
|
||||||
|address, mut card| card.write_byte_io(address as u8, data),
|
|address, mut card| card.write_byte_io(address as u8, data, function),
|
||||||
|address| self.write_byte_io(address as u8, data),
|
|address| self.write_byte_io(address as u8, data),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
supervisor,
|
function,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_word_phys(&self, address: u32) -> Result<u16, BusError> {
|
pub fn read_word_phys(&self, address: u32, function: FunctionCode) -> Result<u16, BusError> {
|
||||||
self.mem_helper(
|
self.mem_helper(
|
||||||
address,
|
address,
|
||||||
|address, mut card| card.read_word(address),
|
|address, mut card| card.read_word(address, function),
|
||||||
|address, mut card| card.read_word_io(address as u8),
|
|address, mut card| card.read_word_io(address as u8, function),
|
||||||
|address| self.read_word_io(address as u8),
|
|address| self.read_word_io(address as u8),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
function,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn read_byte_phys(&self, address: u32) -> Result<u8, BusError> {
|
pub fn read_byte_phys(&self, address: u32, function: FunctionCode) -> Result<u8, BusError> {
|
||||||
self.mem_helper(
|
self.mem_helper(
|
||||||
address,
|
address,
|
||||||
|address, mut card| card.read_byte(address),
|
|address, mut card| card.read_byte(address, function),
|
||||||
|address, mut card| card.read_byte_io(address as u8),
|
|address, mut card| card.read_byte_io(address as u8, function),
|
||||||
|address| self.read_byte_io(address as u8),
|
|address| self.read_byte_io(address as u8),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
function,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn write_word_phys(&self, address: u32, data: u16) -> Result<(), BusError> {
|
pub fn write_word_phys(&self, address: u32, data: u16, function: FunctionCode) -> Result<(), BusError> {
|
||||||
self.mem_helper(
|
self.mem_helper(
|
||||||
address,
|
address,
|
||||||
|address, mut card| card.write_word(address, data),
|
|address, mut card| card.write_word(address, data, function),
|
||||||
|address, mut card| card.write_word_io(address as u8, data),
|
|address, mut card| card.write_word_io(address as u8, data, function),
|
||||||
|address| self.write_word_io(address as u8, data),
|
|address| self.write_word_io(address as u8, data),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
function,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn write_byte_phys(&self, address: u32, data: u8) -> Result<(), BusError> {
|
pub fn write_byte_phys(&self, address: u32, data: u8, function: FunctionCode) -> Result<(), BusError> {
|
||||||
self.mem_helper(
|
self.mem_helper(
|
||||||
address,
|
address,
|
||||||
|address, mut card| card.write_byte(address, data),
|
|address, mut card| card.write_byte(address, data, function),
|
||||||
|address, mut card| card.write_byte_io(address as u8, data),
|
|address, mut card| card.write_byte_io(address as u8, data, function),
|
||||||
|address| self.write_byte_io(address as u8, data),
|
|address| self.write_byte_io(address as u8, data),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
function,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +259,7 @@ impl Backplane {
|
|||||||
mut backplane_io_func: B,
|
mut backplane_io_func: B,
|
||||||
bypass_mmu: bool,
|
bypass_mmu: bool,
|
||||||
write: bool,
|
write: bool,
|
||||||
supervisor: bool,
|
function: FunctionCode,
|
||||||
) -> Result<T, BusError>
|
) -> Result<T, BusError>
|
||||||
where
|
where
|
||||||
M: FnMut(u32, RefMut<'_, dyn Card>) -> NullableResult<T, BusError>,
|
M: FnMut(u32, RefMut<'_, dyn Card>) -> NullableResult<T, BusError>,
|
||||||
@ -272,7 +273,7 @@ impl Backplane {
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.try_as_mmu()
|
.try_as_mmu()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.translate_address(self, address, write, supervisor)
|
.translate_address(self, address, write, function)
|
||||||
{
|
{
|
||||||
NullableResult::Ok(address) => address,
|
NullableResult::Ok(address) => address,
|
||||||
NullableResult::Err(e) => return Err(e),
|
NullableResult::Err(e) => return Err(e),
|
||||||
|
36
src/card.rs
36
src/card.rs
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backplane::{Backplane, InterconnectSenderBuilder},
|
backplane::{Backplane, InterconnectSenderBuilder},
|
||||||
m68k::BusError,
|
m68k::{BusError, FunctionCode},
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use mopa::mopafy;
|
use mopa::mopafy;
|
||||||
@ -67,47 +67,47 @@ pub trait Card: Debug + Display + mopa::Any {
|
|||||||
Ok(Rc::new(RefCell::new(card)))
|
Ok(Rc::new(RefCell::new(card)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte(&mut self, _address: u32) -> NullableResult<u8, BusError> {
|
fn read_byte(&mut self, _address: u32, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
NullableResult::Null
|
NullableResult::Null
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte(&mut self, _address: u32, _data: u8) -> NullableResult<(), BusError> {
|
fn write_byte(&mut self, _address: u32, _data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
NullableResult::Null
|
NullableResult::Null
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte_io(&mut self, _address: u8) -> NullableResult<u8, BusError> {
|
fn read_byte_io(&mut self, _address: u8, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
NullableResult::Null
|
NullableResult::Null
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte_io(&mut self, _address: u8, _data: u8) -> NullableResult<(), BusError> {
|
fn write_byte_io(&mut self, _address: u8, _data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
NullableResult::Null
|
NullableResult::Null
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_word(&mut self, address: u32) -> NullableResult<u16, BusError> {
|
fn read_word(&mut self, address: u32, function: FunctionCode) -> NullableResult<u16, BusError> {
|
||||||
assert!((address & 0x1) == 0);
|
assert!((address & 0x1) == 0);
|
||||||
let upper_byte = self.read_byte(address)?;
|
let upper_byte = self.read_byte(address, function)?;
|
||||||
let lower_byte = self.read_byte(address + 1)?;
|
let lower_byte = self.read_byte(address + 1, function)?;
|
||||||
NullableResult::Ok((u16::from(upper_byte) << 8) | u16::from(lower_byte))
|
NullableResult::Ok((u16::from(upper_byte) << 8) | u16::from(lower_byte))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_word(&mut self, address: u32, data: u16) -> NullableResult<(), BusError> {
|
fn write_word(&mut self, address: u32, data: u16, function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
assert!((address & 0x1) == 0);
|
assert!((address & 0x1) == 0);
|
||||||
self.write_byte(address, (data >> 8) as u8)?;
|
self.write_byte(address, (data >> 8) as u8, function)?;
|
||||||
self.write_byte(address + 1, data as u8)?;
|
self.write_byte(address + 1, data as u8, function)?;
|
||||||
NullableResult::Ok(())
|
NullableResult::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_word_io(&mut self, address: u8) -> NullableResult<u16, BusError> {
|
fn read_word_io(&mut self, address: u8, function: FunctionCode) -> NullableResult<u16, BusError> {
|
||||||
assert!((address & 0x1) == 0);
|
assert!((address & 0x1) == 0);
|
||||||
let upper_byte = self.read_byte_io(address)?;
|
let upper_byte = self.read_byte_io(address, function)?;
|
||||||
let lower_byte = self.read_byte_io(address + 1)?;
|
let lower_byte = self.read_byte_io(address + 1, function)?;
|
||||||
NullableResult::Ok((u16::from(upper_byte) << 8) | u16::from(lower_byte))
|
NullableResult::Ok((u16::from(upper_byte) << 8) | u16::from(lower_byte))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_word_io(&mut self, address: u8, data: u16) -> NullableResult<(), BusError> {
|
fn write_word_io(&mut self, address: u8, data: u16, function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
assert!((address & 0x1) == 0);
|
assert!((address & 0x1) == 0);
|
||||||
self.write_byte_io(address, (data >> 8) as u8)?;
|
self.write_byte_io(address, (data >> 8) as u8, function)?;
|
||||||
self.write_byte_io(address + 1, data as u8)?;
|
self.write_byte_io(address + 1, data as u8, function)?;
|
||||||
NullableResult::Ok(())
|
NullableResult::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ pub trait Mmu: Debug {
|
|||||||
backplane: &Backplane,
|
backplane: &Backplane,
|
||||||
address: u32,
|
address: u32,
|
||||||
write: bool,
|
write: bool,
|
||||||
supervisor: bool,
|
function: FunctionCode
|
||||||
) -> NullableResult<u32, BusError>;
|
) -> NullableResult<u32, BusError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
72
src/m68k.rs
72
src/m68k.rs
@ -162,6 +162,33 @@ impl Display for InsExecError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum FunctionCode {
|
||||||
|
UserData,
|
||||||
|
UserProgram,
|
||||||
|
SupervisorData,
|
||||||
|
SupervisorProgram,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionCode {
|
||||||
|
pub fn new(code: bool, supervisor: bool) -> Self {
|
||||||
|
match (supervisor, code) {
|
||||||
|
(false, false) => Self::UserData,
|
||||||
|
(false, true) => Self::UserProgram,
|
||||||
|
(true, false) => Self::SupervisorData,
|
||||||
|
(true, true) => Self::SupervisorProgram,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_code(self) -> bool {
|
||||||
|
self == Self::UserProgram || self == Self::SupervisorProgram
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_supervisor(self) -> bool {
|
||||||
|
self == Self::SupervisorData || self == Self::SupervisorProgram
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct M68K {
|
pub struct M68K {
|
||||||
dregs: [u32; 8],
|
dregs: [u32; 8],
|
||||||
@ -234,11 +261,12 @@ impl M68K {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
|
let function = FunctionCode::SupervisorProgram;
|
||||||
if let (Ok(ssp_high), Ok(ssp_low), Ok(pc_high), Ok(pc_low)) = (
|
if let (Ok(ssp_high), Ok(ssp_low), Ok(pc_high), Ok(pc_low)) = (
|
||||||
self.read_word(0),
|
self.read_word(0, function),
|
||||||
self.read_word(2),
|
self.read_word(2, function),
|
||||||
self.read_word(4),
|
self.read_word(4, function),
|
||||||
self.read_word(6),
|
self.read_word(6, function),
|
||||||
) {
|
) {
|
||||||
self.ssp = (u32::from(ssp_high) << 16) | u32::from(ssp_low);
|
self.ssp = (u32::from(ssp_high) << 16) | u32::from(ssp_low);
|
||||||
self.vbr = 0;
|
self.vbr = 0;
|
||||||
@ -260,7 +288,7 @@ impl M68K {
|
|||||||
loc: u32,
|
loc: u32,
|
||||||
) -> Result<(Instruction, u32), DisassemblyError<InsExecError>> {
|
) -> Result<(Instruction, u32), DisassemblyError<InsExecError>> {
|
||||||
disas::disasm(loc, &mut |addr| {
|
disas::disasm(loc, &mut |addr| {
|
||||||
self.read_word(addr).map_err(|err| match err {
|
self.read_word(addr, FunctionCode::new(true, self.is_supervisor())).map_err(|err| match err {
|
||||||
InsExecError::AbnormalTrap => InsExecError::AbnormalTrap,
|
InsExecError::AbnormalTrap => InsExecError::AbnormalTrap,
|
||||||
InsExecError::BusError(err) => InsExecError::BusError(DetailedBusError {
|
InsExecError::BusError(err) => InsExecError::BusError(DetailedBusError {
|
||||||
cause: BusErrorCause::ReadingInstruction,
|
cause: BusErrorCause::ReadingInstruction,
|
||||||
@ -1502,30 +1530,32 @@ impl M68K {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_address(&mut self, address: u32, size: Size) -> Result<u32, InsExecError> {
|
fn read_address(&mut self, address: u32, size: Size) -> Result<u32, InsExecError> {
|
||||||
|
let function = FunctionCode::new(false, self.is_supervisor());
|
||||||
let address = address & 0xFF_FFFF;
|
let address = address & 0xFF_FFFF;
|
||||||
match size {
|
match size {
|
||||||
Size::Byte => Ok(u32::from(self.read_byte(address)?)),
|
Size::Byte => Ok(u32::from(self.read_byte(address, function)?)),
|
||||||
Size::Word => Ok(u32::from(self.read_word(address)?)),
|
Size::Word => Ok(u32::from(self.read_word(address, function)?)),
|
||||||
Size::Long => {
|
Size::Long => {
|
||||||
Ok(u32::from(self.read_word(address)?) << 16
|
Ok(u32::from(self.read_word(address, function)?) << 16
|
||||||
| u32::from(self.read_word(address + 2)?))
|
| u32::from(self.read_word(address + 2, function)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_address(&mut self, address: u32, data: u32, size: Size) -> Result<(), InsExecError> {
|
fn write_address(&mut self, address: u32, data: u32, size: Size) -> Result<(), InsExecError> {
|
||||||
|
let function = FunctionCode::new(false, self.is_supervisor());
|
||||||
match size {
|
match size {
|
||||||
Size::Byte => self.write_byte(address, data as u8)?,
|
Size::Byte => self.write_byte(address, data as u8, function)?,
|
||||||
Size::Word => self.write_word(address, data as u16)?,
|
Size::Word => self.write_word(address, data as u16, function)?,
|
||||||
Size::Long => {
|
Size::Long => {
|
||||||
self.write_word(address, (data >> 16) as u16)?;
|
self.write_word(address, (data >> 16) as u16, function)?;
|
||||||
self.write_word(address + 2, data as u16)?;
|
self.write_word(address + 2, data as u16, function)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte(&mut self, address: u32) -> Result<u8, InsExecError> {
|
fn read_byte(&mut self, address: u32, function: FunctionCode) -> Result<u8, InsExecError> {
|
||||||
let address = address & 0xFF_FFFF;
|
let address = address & 0xFF_FFFF;
|
||||||
if self.use_stored_mem_cycles {
|
if self.use_stored_mem_cycles {
|
||||||
let cycle = self.stored_mem_cycles.remove(0);
|
let cycle = self.stored_mem_cycles.remove(0);
|
||||||
@ -1543,7 +1573,7 @@ impl M68K {
|
|||||||
}
|
}
|
||||||
let result = self
|
let result = self
|
||||||
.bus
|
.bus
|
||||||
.read_byte(address, self.is_supervisor())
|
.read_byte(address, function)
|
||||||
.map_err(|_| DetailedBusError {
|
.map_err(|_| DetailedBusError {
|
||||||
address,
|
address,
|
||||||
cause: BusErrorCause::ReadingByte,
|
cause: BusErrorCause::ReadingByte,
|
||||||
@ -1555,7 +1585,7 @@ impl M68K {
|
|||||||
Ok(result?)
|
Ok(result?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte(&mut self, address: u32, data: u8) -> Result<(), InsExecError> {
|
fn write_byte(&mut self, address: u32, data: u8, function: FunctionCode) -> Result<(), InsExecError> {
|
||||||
let address = address & 0xFF_FFFF;
|
let address = address & 0xFF_FFFF;
|
||||||
if self.use_stored_mem_cycles {
|
if self.use_stored_mem_cycles {
|
||||||
let cycle = self.stored_mem_cycles.remove(0);
|
let cycle = self.stored_mem_cycles.remove(0);
|
||||||
@ -1579,7 +1609,7 @@ impl M68K {
|
|||||||
}
|
}
|
||||||
let result = self
|
let result = self
|
||||||
.bus
|
.bus
|
||||||
.write_byte(address, data, self.is_supervisor())
|
.write_byte(address, data, function)
|
||||||
.map_err(|_| DetailedBusError {
|
.map_err(|_| DetailedBusError {
|
||||||
address,
|
address,
|
||||||
cause: BusErrorCause::WritingByte,
|
cause: BusErrorCause::WritingByte,
|
||||||
@ -1594,7 +1624,7 @@ impl M68K {
|
|||||||
Ok(result?)
|
Ok(result?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_word(&mut self, address: u32) -> Result<u16, InsExecError> {
|
fn read_word(&mut self, address: u32, function: FunctionCode) -> Result<u16, InsExecError> {
|
||||||
let address = address & 0xFF_FFFF;
|
let address = address & 0xFF_FFFF;
|
||||||
if address & 0x1 != 0 {
|
if address & 0x1 != 0 {
|
||||||
self.trap(3)?;
|
self.trap(3)?;
|
||||||
@ -1616,7 +1646,7 @@ impl M68K {
|
|||||||
}
|
}
|
||||||
let result = self
|
let result = self
|
||||||
.bus
|
.bus
|
||||||
.read_word(address, self.is_supervisor())
|
.read_word(address, function)
|
||||||
.map_err(|_| DetailedBusError {
|
.map_err(|_| DetailedBusError {
|
||||||
address,
|
address,
|
||||||
cause: BusErrorCause::ReadingWord,
|
cause: BusErrorCause::ReadingWord,
|
||||||
@ -1628,7 +1658,7 @@ impl M68K {
|
|||||||
Ok(result?)
|
Ok(result?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_word(&mut self, address: u32, data: u16) -> Result<(), InsExecError> {
|
fn write_word(&mut self, address: u32, data: u16, function: FunctionCode) -> Result<(), InsExecError> {
|
||||||
let address = address & 0xFF_FFFF;
|
let address = address & 0xFF_FFFF;
|
||||||
if address & 0x1 != 0 {
|
if address & 0x1 != 0 {
|
||||||
self.trap(3)?;
|
self.trap(3)?;
|
||||||
@ -1656,7 +1686,7 @@ impl M68K {
|
|||||||
}
|
}
|
||||||
let result = self
|
let result = self
|
||||||
.bus
|
.bus
|
||||||
.write_word(address, data, self.is_supervisor())
|
.write_word(address, data, function)
|
||||||
.map_err(|_| DetailedBusError {
|
.map_err(|_| DetailedBusError {
|
||||||
address,
|
address,
|
||||||
cause: BusErrorCause::WritingWord,
|
cause: BusErrorCause::WritingWord,
|
||||||
|
24
src/main.rs
24
src/main.rs
@ -21,7 +21,7 @@ use clap::Parser;
|
|||||||
use disas::DisassemblyError;
|
use disas::DisassemblyError;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use m68k::InsExecError;
|
use m68k::{FunctionCode, InsExecError};
|
||||||
use parse_int::parse;
|
use parse_int::parse;
|
||||||
use reedline_repl_rs::{
|
use reedline_repl_rs::{
|
||||||
clap::{builder::BoolishValueParser, Arg, ArgAction, Command},
|
clap::{builder::BoolishValueParser, Arg, ArgAction, Command},
|
||||||
@ -280,25 +280,26 @@ fn main() -> Result<(), anyhow::Error> {
|
|||||||
}
|
}
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
let bus = state.cpu.bus_mut();
|
let bus = state.cpu.bus_mut();
|
||||||
|
let function = FunctionCode::SupervisorData;
|
||||||
if args.get_flag("phys") {
|
if args.get_flag("phys") {
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
match size {
|
match size {
|
||||||
peek::Size::Byte => data.push(u32::from(bus.read_byte_phys(addr + i)?)),
|
peek::Size::Byte => data.push(u32::from(bus.read_byte_phys(addr + i, function)?)),
|
||||||
peek::Size::Word => data.push(u32::from(bus.read_word_phys(addr + (i * 2))?)),
|
peek::Size::Word => data.push(u32::from(bus.read_word_phys(addr + (i * 2), function)?)),
|
||||||
peek::Size::LongWord => data.push(
|
peek::Size::LongWord => data.push(
|
||||||
u32::from(bus.read_word_phys(addr + (i * 4))?) << 16
|
u32::from(bus.read_word_phys(addr + (i * 4), function)?) << 16
|
||||||
| u32::from(bus.read_word_phys(addr + (i * 4) + 2)?),
|
| u32::from(bus.read_word_phys(addr + (i * 4) + 2, function)?),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
match size {
|
match size {
|
||||||
peek::Size::Byte => data.push(u32::from(bus.read_byte(addr + i, true)?)),
|
peek::Size::Byte => data.push(u32::from(bus.read_byte(addr + i, function)?)),
|
||||||
peek::Size::Word => data.push(u32::from(bus.read_word(addr + (i * 2), true)?)),
|
peek::Size::Word => data.push(u32::from(bus.read_word(addr + (i * 2), function)?)),
|
||||||
peek::Size::LongWord => data.push(
|
peek::Size::LongWord => data.push(
|
||||||
u32::from(bus.read_word(addr + (i * 4), true)?) << 16
|
u32::from(bus.read_word(addr + (i * 4), function)?) << 16
|
||||||
| u32::from(bus.read_word(addr + (i * 4) + 2, true)?),
|
| u32::from(bus.read_word(addr + (i * 4) + 2, function)?),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,15 +331,16 @@ fn main() -> Result<(), anyhow::Error> {
|
|||||||
.about("Write to a memory address"),
|
.about("Write to a memory address"),
|
||||||
|args, state| {
|
|args, state| {
|
||||||
let address = parse::<u32>(args.get_one::<String>("address").unwrap())?;
|
let address = parse::<u32>(args.get_one::<String>("address").unwrap())?;
|
||||||
|
let function = FunctionCode::SupervisorData;
|
||||||
if args.get_flag("word") {
|
if args.get_flag("word") {
|
||||||
if (address & 0x1) != 0 {
|
if (address & 0x1) != 0 {
|
||||||
return Err(anyhow!("Cannot poke a word to a non-aligned address"));
|
return Err(anyhow!("Cannot poke a word to a non-aligned address"));
|
||||||
}
|
}
|
||||||
let data = parse::<u16>(args.get_one::<String>("data").unwrap())?;
|
let data = parse::<u16>(args.get_one::<String>("data").unwrap())?;
|
||||||
state.cpu.bus_mut().write_word(address, data, true)?;
|
state.cpu.bus_mut().write_word(address, data, function)?;
|
||||||
} else {
|
} else {
|
||||||
let data = parse::<u8>(args.get_one::<String>("data").unwrap())?;
|
let data = parse::<u8>(args.get_one::<String>("data").unwrap())?;
|
||||||
state.cpu.bus_mut().write_byte(address, data, true)?;
|
state.cpu.bus_mut().write_byte(address, data, function)?;
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
14
src/mmu.rs
14
src/mmu.rs
@ -5,7 +5,7 @@ use nullable_result::NullableResult;
|
|||||||
use crate::{
|
use crate::{
|
||||||
backplane::Backplane,
|
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,
|
m68k::{BusError, FunctionCode},
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -39,8 +39,8 @@ impl MmuCard {
|
|||||||
if print_debug {
|
if print_debug {
|
||||||
println!("Mapping is at {mapping_address:#x}");
|
println!("Mapping is at {mapping_address:#x}");
|
||||||
}
|
}
|
||||||
let mapping_hi = backplane.read_word_phys(mapping_address)?;
|
let mapping_hi = backplane.read_word_phys(mapping_address, FunctionCode::SupervisorData)?;
|
||||||
let mapping_lo = backplane.read_word_phys(mapping_address + 2)?;
|
let mapping_lo = backplane.read_word_phys(mapping_address + 2, FunctionCode::SupervisorData)?;
|
||||||
NullableResult::Ok((u32::from(mapping_hi) << 16 | u32::from(mapping_lo)) | TLB_MAPPING_FLAG_VALID)
|
NullableResult::Ok((u32::from(mapping_hi) << 16 | u32::from(mapping_lo)) | TLB_MAPPING_FLAG_VALID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ impl Card for MmuCard {
|
|||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
fn read_byte_io(&mut self, address: u8, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
match address {
|
match address {
|
||||||
(0x0..=0xF) => {
|
(0x0..=0xF) => {
|
||||||
let map_no = (address / 4) as usize;
|
let map_no = (address / 4) as usize;
|
||||||
@ -77,7 +77,7 @@ impl Card for MmuCard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte_io(&mut self, address: u8, data: u8) -> NullableResult<(), BusError> {
|
fn write_byte_io(&mut self, address: u8, data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
match address {
|
match address {
|
||||||
(0x0..=0xF) => {
|
(0x0..=0xF) => {
|
||||||
let map_no = (address / 4) as usize;
|
let map_no = (address / 4) as usize;
|
||||||
@ -344,7 +344,7 @@ impl Mmu for MmuCard {
|
|||||||
backplane: &Backplane,
|
backplane: &Backplane,
|
||||||
address: u32,
|
address: u32,
|
||||||
write: bool,
|
write: bool,
|
||||||
supervisor: bool,
|
function: FunctionCode,
|
||||||
) -> NullableResult<u32, BusError> {
|
) -> NullableResult<u32, BusError> {
|
||||||
let print_debug = self.print_debug;
|
let print_debug = self.print_debug;
|
||||||
if self.enabled {
|
if self.enabled {
|
||||||
@ -368,7 +368,7 @@ impl Mmu for MmuCard {
|
|||||||
mapping
|
mapping
|
||||||
};
|
};
|
||||||
if mapping & MAPPING_FLAG_PRESENT > 0 {
|
if mapping & MAPPING_FLAG_PRESENT > 0 {
|
||||||
if !supervisor && (mapping & MAPPING_FLAG_USER == 0) {
|
if !function.is_supervisor() && (mapping & MAPPING_FLAG_USER == 0) {
|
||||||
if print_debug {
|
if print_debug {
|
||||||
println!("Page not user accessible");
|
println!("Page not user accessible");
|
||||||
}
|
}
|
||||||
|
10
src/ram.rs
10
src/ram.rs
@ -7,7 +7,7 @@ use toml::Value;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
card::{u16_get_be_byte, u32_get_be_byte, Card},
|
card::{u16_get_be_byte, u32_get_be_byte, Card},
|
||||||
m68k::BusError,
|
m68k::{BusError, FunctionCode},
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ impl Card for Ram {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn read_byte(&mut self, address: u32) -> NullableResult<u8, BusError> {
|
fn read_byte(&mut self, address: u32, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return NullableResult::Null;
|
return NullableResult::Null;
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ impl Card for Ram {
|
|||||||
self.data.get(address as usize).copied().into()
|
self.data.get(address as usize).copied().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte(&mut self, address: u32, data: u8) -> NullableResult<(), BusError> {
|
fn write_byte(&mut self, address: u32, data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return NullableResult::Null;
|
return NullableResult::Null;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ impl Card for Ram {
|
|||||||
NullableResult::Ok(())
|
NullableResult::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte_io(&mut self, address: u8, data: u8) -> NullableResult<(), BusError> {
|
fn write_byte_io(&mut self, address: u8, data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
match address {
|
match address {
|
||||||
0 => self.start = self.start & !0xFF00_0000 | (u32::from(data) << 24),
|
0 => self.start = self.start & !0xFF00_0000 | (u32::from(data) << 24),
|
||||||
1 => self.start = self.start & !0x00FF_0000 | (u32::from(data) << 16),
|
1 => self.start = self.start & !0x00FF_0000 | (u32::from(data) << 16),
|
||||||
@ -68,7 +68,7 @@ impl Card for Ram {
|
|||||||
NullableResult::Ok(())
|
NullableResult::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
fn read_byte_io(&mut self, address: u8, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
match address {
|
match address {
|
||||||
0 => NullableResult::Ok((self.start >> 24) as u8),
|
0 => NullableResult::Ok((self.start >> 24) as u8),
|
||||||
1 => NullableResult::Ok((self.start >> 16) as u8),
|
1 => NullableResult::Ok((self.start >> 16) as u8),
|
||||||
|
10
src/rom.rs
10
src/rom.rs
@ -7,7 +7,7 @@ use serde::Deserialize;
|
|||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backplane::Backplane, card::{u16_get_be_byte, u16_set_be_byte, Card}, m68k::BusError, register
|
backplane::Backplane, card::{u16_get_be_byte, u16_set_be_byte, Card}, m68k::{BusError, FunctionCode}, register
|
||||||
};
|
};
|
||||||
|
|
||||||
const ID: u16 = 1;
|
const ID: u16 = 1;
|
||||||
@ -47,7 +47,7 @@ impl Card for Rom {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte(&mut self, address: u32) -> NullableResult<u8, BusError> {
|
fn read_byte(&mut self, address: u32, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
if !self.enabled | ((address >> 16) as u16 != self.start) {
|
if !self.enabled | ((address >> 16) as u16 != self.start) {
|
||||||
return NullableResult::Null;
|
return NullableResult::Null;
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ impl Card for Rom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte(&mut self, address: u32, data: u8) -> NullableResult<(), BusError> {
|
fn write_byte(&mut self, address: u32, data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
if !self.enabled | ((address >> 16) as u16 != self.start) {
|
if !self.enabled | ((address >> 16) as u16 != self.start) {
|
||||||
return NullableResult::Null;
|
return NullableResult::Null;
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ impl Card for Rom {
|
|||||||
NullableResult::Ok(())
|
NullableResult::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
fn read_byte_io(&mut self, address: u8, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
match address {
|
match address {
|
||||||
(0..=0xEF) => NullableResult::Ok(self.ram[address as usize]),
|
(0..=0xEF) => NullableResult::Ok(self.ram[address as usize]),
|
||||||
(0xF0..=0xF1) => NullableResult::Ok(u16_get_be_byte(self.start, address - 0xF0)),
|
(0xF0..=0xF1) => NullableResult::Ok(u16_get_be_byte(self.start, address - 0xF0)),
|
||||||
@ -81,7 +81,7 @@ impl Card for Rom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte_io(&mut self, address: u8, data: u8) -> NullableResult<(), BusError> {
|
fn write_byte_io(&mut self, address: u8, data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
match address {
|
match address {
|
||||||
(0..=0xEF) => {
|
(0..=0xEF) => {
|
||||||
self.ram[address as usize] = data;
|
self.ram[address as usize] = data;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
backplane::Backplane,
|
backplane::Backplane,
|
||||||
card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card},
|
card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card},
|
||||||
m68k::BusError,
|
m68k::{BusError, FunctionCode},
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
@ -72,7 +72,7 @@ impl Card for Storage {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
fn read_byte_io(&mut self, address: u8, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
match address {
|
match address {
|
||||||
0x0..=0x3 => NullableResult::Ok(u32_get_be_byte(self.sector, address)),
|
0x0..=0x3 => NullableResult::Ok(u32_get_be_byte(self.sector, address)),
|
||||||
0x4..=0x7 => NullableResult::Ok(u32_get_be_byte(self.count, address - 0x4)),
|
0x4..=0x7 => NullableResult::Ok(u32_get_be_byte(self.count, address - 0x4)),
|
||||||
@ -89,7 +89,7 @@ impl Card for Storage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte_io(&mut self, address: u8, data: u8) -> NullableResult<(), BusError> {
|
fn write_byte_io(&mut self, address: u8, data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
match address {
|
match address {
|
||||||
0x0..=0x3 => {
|
0x0..=0x3 => {
|
||||||
self.sector = u32_set_be_byte(self.sector, address, data);
|
self.sector = u32_set_be_byte(self.sector, address, data);
|
||||||
@ -156,7 +156,7 @@ impl Card for Storage {
|
|||||||
// Closure is used to drop the mutex guard
|
// Closure is used to drop the mutex guard
|
||||||
// between pop calls to prevent deadlock
|
// between pop calls to prevent deadlock
|
||||||
while let Some(data) = (|| self.read_data.pop_front())() {
|
while let Some(data) = (|| self.read_data.pop_front())() {
|
||||||
backplane.write_byte(address, data, true).unwrap();
|
backplane.write_byte(address, data, FunctionCode::SupervisorData).unwrap();
|
||||||
address += 1;
|
address += 1;
|
||||||
}
|
}
|
||||||
self.transfer = false;
|
self.transfer = false;
|
||||||
|
@ -5,7 +5,7 @@ use toml::Value;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
card::{u16_get_be_byte, Card},
|
card::{u16_get_be_byte, Card},
|
||||||
m68k::BusError,
|
m68k::{BusError, FunctionCode},
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,14 +28,14 @@ impl Card for Term {
|
|||||||
Ok(Self)
|
Ok(Self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
fn read_byte_io(&mut self, address: u8, _function: FunctionCode) -> NullableResult<u8, BusError> {
|
||||||
match address {
|
match address {
|
||||||
(0xFE..=0xFF) => NullableResult::Ok(u16_get_be_byte(ID, address - 0xFE)),
|
(0xFE..=0xFF) => NullableResult::Ok(u16_get_be_byte(ID, address - 0xFE)),
|
||||||
_ => NullableResult::Null,
|
_ => NullableResult::Null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte_io(&mut self, address: u8, data: u8) -> NullableResult<(), BusError> {
|
fn write_byte_io(&mut self, address: u8, data: u8, _function: FunctionCode) -> NullableResult<(), BusError> {
|
||||||
if address == 0 {
|
if address == 0 {
|
||||||
print!("{}", data as char);
|
print!("{}", data as char);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user