2021-09-28 23:09:38 +00:00
|
|
|
|
|
|
|
use std::fs;
|
|
|
|
use std::slice::Iter;
|
|
|
|
|
|
|
|
use crate::error::Error;
|
|
|
|
|
|
|
|
|
|
|
|
pub type Address = u64;
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
pub trait Addressable {
|
|
|
|
fn len(&self) -> usize;
|
2021-10-06 02:58:22 +00:00
|
|
|
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error>;
|
|
|
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error>;
|
|
|
|
|
|
|
|
fn read_u8(&mut self, addr: Address) -> Result<u8, Error> {
|
|
|
|
Ok(self.read(addr, 1)?[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_beu16(&mut self, addr: Address) -> Result<u16, Error> {
|
|
|
|
Ok(read_beu16(&self.read(addr, 2)?))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_beu32(&mut self, addr: Address) -> Result<u32, Error> {
|
|
|
|
Ok(read_beu32(&self.read(addr, 4)?))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_u8(&mut self, addr: Address, value: u8) -> Result<(), Error> {
|
|
|
|
let data = [value];
|
|
|
|
self.write(addr, &data)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_beu16(&mut self, addr: Address, value: u16) -> Result<(), Error> {
|
|
|
|
let data = write_beu16(value);
|
|
|
|
self.write(addr, &data)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_beu32(&mut self, addr: Address, value: u32) -> Result<(), Error> {
|
|
|
|
let data = write_beu32(value);
|
|
|
|
self.write(addr, &data)
|
|
|
|
}
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
pub struct MemoryBlock {
|
2021-09-28 23:09:38 +00:00
|
|
|
pub contents: Vec<u8>,
|
|
|
|
}
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
impl MemoryBlock {
|
|
|
|
pub fn new(contents: Vec<u8>) -> MemoryBlock {
|
|
|
|
MemoryBlock {
|
|
|
|
contents
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
pub fn load(filename: &str) -> Result<MemoryBlock, Error> {
|
2021-09-28 23:09:38 +00:00
|
|
|
match fs::read(filename) {
|
2021-09-30 06:21:11 +00:00
|
|
|
Ok(contents) => Ok(MemoryBlock::new(contents)),
|
2021-09-28 23:09:38 +00:00
|
|
|
Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))),
|
|
|
|
}
|
|
|
|
}
|
2021-10-03 16:55:20 +00:00
|
|
|
|
|
|
|
pub fn load_at(&mut self, mut addr: Address, filename: &str) -> Result<(), Error> {
|
|
|
|
match fs::read(filename) {
|
|
|
|
Ok(contents) => {
|
|
|
|
for byte in contents {
|
|
|
|
self.contents[addr as usize] = byte;
|
|
|
|
addr += 1;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))),
|
|
|
|
}
|
|
|
|
}
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
impl Addressable for MemoryBlock {
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
self.contents.len()
|
|
|
|
}
|
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
|
|
|
|
Ok(self.contents[(addr as usize) .. (addr as usize + count)].to_vec())
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
fn write(&mut self, mut addr: Address, data: &[u8]) -> Result<(), Error> {
|
2021-09-28 23:09:38 +00:00
|
|
|
for byte in data {
|
2021-09-30 06:21:11 +00:00
|
|
|
self.contents[addr as usize] = *byte;
|
2021-09-30 04:52:38 +00:00
|
|
|
addr += 1;
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
2021-10-06 02:58:22 +00:00
|
|
|
Ok(())
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-28 23:09:38 +00:00
|
|
|
pub struct AddressSpace {
|
|
|
|
pub segments: Vec<Segment>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AddressSpace {
|
|
|
|
pub fn new() -> AddressSpace {
|
|
|
|
AddressSpace {
|
|
|
|
segments: vec!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
pub fn insert(&mut self, base: Address, contents: Box<dyn Addressable>) {
|
|
|
|
let seg = Segment::new(base, contents);
|
2021-09-28 23:09:38 +00:00
|
|
|
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]);
|
|
|
|
}
|
|
|
|
}
|
2021-09-30 04:52:38 +00:00
|
|
|
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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]);
|
|
|
|
}
|
|
|
|
}
|
2021-09-30 04:52:38 +00:00
|
|
|
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-01 19:25:23 +00:00
|
|
|
pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) {
|
2021-09-30 19:58:11 +00:00
|
|
|
while count > 0 {
|
|
|
|
let mut line = format!("{:#010x}: ", addr);
|
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-03 04:59:28 +00:00
|
|
|
|
2021-10-02 00:53:55 +00:00
|
|
|
let to = if count < 16 { count / 2 } else { 8 };
|
|
|
|
for i in 0..to {
|
2021-10-02 05:06:53 +00:00
|
|
|
let word = self.read_beu16(addr);
|
|
|
|
if word.is_err() {
|
|
|
|
println!("{}", line);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
line += &format!("{:#06x} ", word.unwrap());
|
2021-09-30 19:58:11 +00:00
|
|
|
addr += 2;
|
|
|
|
count -= 2;
|
|
|
|
}
|
|
|
|
println!("{}", line);
|
|
|
|
}
|
|
|
|
}
|
2021-10-06 02:58:22 +00:00
|
|
|
}
|
2021-09-30 19:58:11 +00:00
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
impl Addressable for AddressSpace {
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
let seg = &self.segments[self.segments.len() - 1];
|
|
|
|
(seg.base as usize) + seg.contents.len()
|
|
|
|
}
|
2021-09-30 19:58:11 +00:00
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
|
2021-10-01 19:25:23 +00:00
|
|
|
let mut seg = self.get_segment_mut(addr)?;
|
2021-10-04 04:05:10 +00:00
|
|
|
let relative_addr = addr - seg.base;
|
2021-10-04 18:13:10 +00:00
|
|
|
if relative_addr as usize + count > seg.contents.len() {
|
2021-10-04 04:05:10 +00:00
|
|
|
Err(Error::new(&format!("Error reading address {:#010x}", addr)))
|
|
|
|
} else {
|
2021-10-06 02:58:22 +00:00
|
|
|
seg.contents.read(relative_addr, count)
|
2021-10-04 04:05:10 +00:00
|
|
|
}
|
2021-09-30 04:52:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
2021-09-30 00:11:48 +00:00
|
|
|
let seg = self.get_segment_mut(addr)?;
|
2021-10-06 02:58:22 +00:00
|
|
|
seg.contents.write(addr - seg.base, data)
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-04 04:05:10 +00:00
|
|
|
#[inline(always)]
|
2021-10-06 02:58:22 +00:00
|
|
|
pub fn read_beu16(data: &[u8]) -> u16 {
|
2021-10-04 04:05:10 +00:00
|
|
|
(data[0] as u16) << 8 |
|
|
|
|
(data[1] as u16)
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-04 04:05:10 +00:00
|
|
|
#[inline(always)]
|
2021-10-06 02:58:22 +00:00
|
|
|
pub fn read_beu32(data: &[u8]) -> u32 {
|
2021-10-04 04:05:10 +00:00
|
|
|
(data[0] as u32) << 24 |
|
|
|
|
(data[1] as u32) << 16 |
|
|
|
|
(data[2] as u32) << 8 |
|
|
|
|
(data[3] as u32)
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn write_beu16(value: u16) -> [u8; 2] {
|
|
|
|
[
|
|
|
|
(value >> 8) as u8,
|
|
|
|
value as u8,
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn write_beu32(value: u32) -> [u8; 4] {
|
|
|
|
[
|
|
|
|
(value >> 24) as u8,
|
|
|
|
(value >> 16) as u8,
|
|
|
|
(value >> 8) as u8,
|
|
|
|
value as u8,
|
|
|
|
]
|
|
|
|
}
|