moa/src/memory.rs
transistor 10e905674b Added MUL, DIV, NEG, DBcc, and Scc instructions, and fixed issue with ADD/SUB flags
With ADDA, SUBA, and ADDQ/SUBQ when the target is an address register, the condition
flags should not be changed, but the code was changing them, which caused problems.
I've fixed it by making the ADD/SUB executions check for an address target and
will not update flags in that case.  This should only occur when the actual instruction
was an ADDA or ADDQ with an address register target
2021-10-02 21:59:28 -07:00

193 lines
5.5 KiB
Rust

use std::fs;
use std::slice::Iter;
use crate::error::Error;
pub type Address = u64;
pub trait Addressable {
fn len(&self) -> usize;
fn read(&mut self, addr: Address, count: usize) -> Vec<u8>;
fn write(&mut self, addr: Address, data: &[u8]);
}
pub struct MemoryBlock {
pub contents: Vec<u8>,
}
impl MemoryBlock {
pub fn new(contents: Vec<u8>) -> MemoryBlock {
MemoryBlock {
contents
}
}
pub fn load(filename: &str) -> Result<MemoryBlock, Error> {
match fs::read(filename) {
Ok(contents) => Ok(MemoryBlock::new(contents)),
Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))),
}
}
}
impl Addressable for MemoryBlock {
fn len(&self) -> usize {
self.contents.len()
}
fn read(&mut self, addr: Address, count: usize) -> Vec<u8> {
let size = if addr as usize + count < self.contents.len() { addr as usize + count } else { self.contents.len() };
self.contents[(addr as usize) .. size].to_vec()
}
fn write(&mut self, mut addr: Address, data: &[u8]) {
for byte in data {
self.contents[addr as usize] = *byte;
addr += 1;
}
}
}
pub struct Segment {
pub base: Address,
pub contents: Box<dyn Addressable>,
}
impl Segment {
pub fn new(base: Address, contents: Box<dyn Addressable>) -> Segment {
Segment {
base,
contents,
}
}
}
pub struct AddressSpace {
pub segments: Vec<Segment>,
}
impl AddressSpace {
pub fn new() -> AddressSpace {
AddressSpace {
segments: vec!(),
}
}
pub fn insert(&mut self, base: Address, contents: Box<dyn Addressable>) {
let seg = Segment::new(base, contents);
for i in 0..self.segments.len() {
if self.segments[i].base > seg.base {
self.segments.insert(i, seg);
return;
}
}
self.segments.insert(0, seg);
}
pub fn get_segment(&self, addr: Address) -> Result<&Segment, Error> {
for i in 0..self.segments.len() {
if addr >= self.segments[i].base && addr <= (self.segments[i].base + self.segments[i].contents.len() as Address) {
return Ok(&self.segments[i]);
}
}
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
}
pub fn get_segment_mut(&mut self, addr: Address) -> Result<&mut Segment, Error> {
for i in 0..self.segments.len() {
if addr >= self.segments[i].base && addr <= (self.segments[i].base + self.segments[i].contents.len() as Address) {
return Ok(&mut self.segments[i]);
}
}
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
}
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 i 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);
}
}
pub fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
let mut seg = self.get_segment_mut(addr)?;
Ok(seg.contents.read(addr - seg.base, count))
}
pub fn read_u8(&mut self, addr: Address) -> Result<u8, Error> {
let mut seg = self.get_segment_mut(addr)?;
Ok(*seg.contents.read(addr - seg.base, 1).iter().next().ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
}
pub fn read_beu16(&mut self, addr: Address) -> Result<u16, Error> {
let mut seg = self.get_segment_mut(addr)?;
Ok(read_beu16(seg.contents.read(addr - seg.base, 2).iter()).ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
}
pub fn read_beu32(&mut self, addr: Address) -> Result<u32, Error> {
let mut seg = self.get_segment_mut(addr)?;
Ok(read_beu32(seg.contents.read(addr - seg.base, 4).iter()).ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
}
pub fn write_u8(&mut self, addr: Address, value: u8) -> Result<(), Error> {
let seg = self.get_segment_mut(addr)?;
let data = [value];
Ok(seg.contents.write(addr - seg.base, &data))
}
pub fn write_beu16(&mut self, addr: Address, value: u16) -> Result<(), Error> {
let seg = self.get_segment_mut(addr)?;
let data = [
(value >> 8) as u8,
value as u8,
];
Ok(seg.contents.write(addr - seg.base, &data))
}
pub fn write_beu32(&mut self, addr: Address, value: u32) -> Result<(), Error> {
let seg = self.get_segment_mut(addr)?;
let data = [
(value >> 24) as u8,
(value >> 16) as u8,
(value >> 8) as u8,
value as u8,
];
Ok(seg.contents.write(addr - seg.base, &data))
}
}
pub fn read_beu16(mut iter: Iter<u8>) -> Option<u16> {
Some(
(*iter.next()? as u16) << 8 |
(*iter.next()? as u16))
}
pub fn read_beu32(mut iter: Iter<u8>) -> Option<u32> {
Some(
(*iter.next()? as u32) << 24 |
(*iter.next()? as u32) << 16 |
(*iter.next()? as u32) << 8 |
(*iter.next()? as u32))
}