use crate::M68000;
use crate::addressing_modes::{EffectiveAddress, AddressingMode};
use crate::exception::{ACCESS_ERROR, ADDRESS_ERROR};
use crate::execution_times as EXEC;
use crate::instruction::Size;
use crate::utils::IsEven;
type GetResult<T> = Result<T, u8>;
type SetResult = Result<(), u8>;
pub trait MemoryAccess {
#[must_use]
fn get_byte(&mut self, addr: u32) -> Option<u8>;
#[must_use]
fn get_word(&mut self, addr: u32) -> Option<u16>;
#[must_use]
fn get_long(&mut self, addr: u32) -> Option<u32> {
Some((self.get_word(addr)? as u32) << 16 | self.get_word(addr + 2)? as u32)
}
#[must_use]
fn set_byte(&mut self, addr: u32, value: u8) -> Option<()>;
#[must_use]
fn set_word(&mut self, addr: u32, value: u16) -> Option<()>;
#[must_use]
fn set_long(&mut self, addr: u32, value: u32) -> Option<()> {
self.set_word(addr, (value >> 16) as u16)?;
self.set_word(addr + 2, value as u16)
}
#[must_use]
fn iter_u16(&mut self, addr: u32) -> MemoryIter where Self: Sized {
MemoryIter { memory: self, next_addr: addr }
}
fn reset_instruction(&mut self);
}
pub struct MemoryIter<'a> {
pub memory: &'a mut dyn MemoryAccess,
pub next_addr: u32,
}
impl Iterator for MemoryIter<'_> {
type Item = GetResult<u16>;
fn next(&mut self) -> Option<Self::Item> {
if self.next_addr.is_even() {
let data = self.memory.get_word(self.next_addr);
self.next_addr += 2;
Some(data.ok_or(ACCESS_ERROR))
} else {
Some(Err(ADDRESS_ERROR))
}
}
}
impl M68000 {
#[must_use]
pub(super) fn get_byte(&mut self, memory: &mut impl MemoryAccess, ea: &mut EffectiveAddress, exec_time: &mut usize) -> GetResult<u8> {
match ea.mode {
AddressingMode::Drd(reg) => Ok(self.regs.d[reg as usize] as u8),
AddressingMode::Immediate(imm) => {
*exec_time += EXEC::EA_IMMEDIATE;
Ok(imm as u8)
},
_ => memory.get_byte(self.get_effective_address(ea, exec_time)).ok_or(ACCESS_ERROR),
}
}
#[must_use]
pub(super) fn get_word(&mut self, memory: &mut impl MemoryAccess, ea: &mut EffectiveAddress, exec_time: &mut usize) -> GetResult<u16> {
match ea.mode {
AddressingMode::Drd(reg) => Ok(self.regs.d[reg as usize] as u16),
AddressingMode::Ard(reg) => Ok(self.a(reg) as u16),
AddressingMode::Immediate(imm) => {
*exec_time += EXEC::EA_IMMEDIATE;
Ok(imm as u16)
},
_ => {
let addr = self.get_effective_address(ea, exec_time);
memory.get_word(addr.even()?).ok_or(ACCESS_ERROR)
},
}
}
#[must_use]
pub(super) fn get_long(&mut self, memory: &mut impl MemoryAccess, ea: &mut EffectiveAddress, exec_time: &mut usize) -> GetResult<u32> {
match ea.mode {
AddressingMode::Drd(reg) => Ok(self.regs.d[reg as usize]),
AddressingMode::Ard(reg) => Ok(self.a(reg)),
AddressingMode::Immediate(imm) => {
*exec_time += EXEC::EA_IMMEDIATE + 4;
Ok(imm)
},
_ => {
let addr = self.get_effective_address(ea, exec_time);
let r = memory.get_long(addr.even()?).ok_or(ACCESS_ERROR);
*exec_time += 4;
r
},
}
}
#[must_use]
pub(super) fn set_byte(&mut self, memory: &mut impl MemoryAccess, ea: &mut EffectiveAddress, exec_time: &mut usize, value: u8) -> SetResult {
match ea.mode {
AddressingMode::Drd(reg) => Ok(self.d_byte(reg, value)),
_ => memory.set_byte(self.get_effective_address(ea, exec_time), value).ok_or(ACCESS_ERROR),
}
}
#[must_use]
pub(super) fn set_word(&mut self, memory: &mut impl MemoryAccess, ea: &mut EffectiveAddress, exec_time: &mut usize, value: u16) -> SetResult {
match ea.mode {
AddressingMode::Drd(reg) => Ok(self.d_word(reg, value)),
AddressingMode::Ard(reg) => Ok(*self.a_mut(reg) = value as i16 as u32),
_ => {
let addr = self.get_effective_address(ea, exec_time);
memory.set_word(addr.even()?, value).ok_or(ACCESS_ERROR)
},
}
}
#[must_use]
pub(super) fn set_long(&mut self, memory: &mut impl MemoryAccess, ea: &mut EffectiveAddress, exec_time: &mut usize, value: u32) -> SetResult {
match ea.mode {
AddressingMode::Drd(reg) => Ok(self.regs.d[reg as usize] = value),
AddressingMode::Ard(reg) => Ok(*self.a_mut(reg) = value),
_ => {
let addr = self.get_effective_address(ea, exec_time);
let r = memory.set_long(addr.even()?, value).ok_or(ACCESS_ERROR);
*exec_time += 4;
r
},
}
}
#[must_use]
pub fn get_next_word(&mut self, memory: &mut impl MemoryAccess) -> GetResult<u16> {
let data = memory.get_word(self.regs.pc.even()?).ok_or(ACCESS_ERROR);
self.regs.pc += 2;
data
}
#[must_use]
pub fn get_next_long(&mut self, memory: &mut impl MemoryAccess) -> GetResult<u32> {
let data = memory.get_long(self.regs.pc.even()?).ok_or(ACCESS_ERROR);
self.regs.pc += 4;
data
}
#[must_use]
pub fn peek_next_word(&self, memory: &mut impl MemoryAccess) -> GetResult<u16> {
memory.get_word(self.regs.pc.even()?).ok_or(ACCESS_ERROR)
}
#[must_use]
pub(super) fn pop_word(&mut self, memory: &mut impl MemoryAccess) -> GetResult<u16> {
let addr = self.ariwpo(7, Size::Word);
memory.get_word(addr.even()?).ok_or(ACCESS_ERROR)
}
#[must_use]
pub(super) fn pop_long(&mut self, memory: &mut impl MemoryAccess) -> GetResult<u32> {
let addr = self.ariwpo(7, Size::Long);
memory.get_long(addr.even()?).ok_or(ACCESS_ERROR)
}
#[must_use]
pub(super) fn push_word(&mut self, memory: &mut impl MemoryAccess, value: u16) -> SetResult {
let addr = self.ariwpr(7, Size::Word);
memory.set_word(addr.even()?, value).ok_or(ACCESS_ERROR)
}
#[must_use]
pub(super) fn push_long(&mut self, memory: &mut impl MemoryAccess, value: u32) -> SetResult {
let addr = self.ariwpr(7, Size::Long);
memory.set_long(addr.even()?, value).ok_or(ACCESS_ERROR)
}
}