Refactored such that System is the top level object

This commit is contained in:
transistor 2021-10-06 16:14:56 -07:00
parent 5ea2ccc128
commit e186637f49
10 changed files with 494 additions and 404 deletions

View File

@ -1,9 +1,9 @@
use crate::error::Error;
use crate::memory::{Address, Addressable, AddressSpace};
use crate::system::System;
use crate::memory::Address;
use super::execute::{MC68010};
use super::decode::{Instruction, Target, Size, Direction, Condition, ControlRegister, RegisterType};
pub struct StackTracer {
pub calls: Vec<u32>,
@ -66,8 +66,8 @@ impl MC68010 {
}
}
pub fn run_debugger(&mut self, space: &mut AddressSpace) {
self.dump_state(space);
pub fn run_debugger(&mut self, system: &System) {
self.dump_state(system);
match self.debugger.step_until_return {
Some(level) if level == self.debugger.stack_tracer.calls.len() => { self.debugger.step_until_return = None; },
@ -79,7 +79,7 @@ impl MC68010 {
let mut buffer = String::new();
std::io::stdin().read_line(&mut buffer).unwrap();
let args: Vec<&str> = buffer.split_whitespace().collect();
match self.run_debugger_command(space, args) {
match self.run_debugger_command(system, args) {
Ok(true) => return,
Ok(false) => { },
Err(err) => {
@ -89,7 +89,7 @@ impl MC68010 {
}
}
pub fn run_debugger_command(&mut self, space: &mut AddressSpace, args: Vec<&str>) -> Result<bool, Error> {
pub fn run_debugger_command(&mut self, system: &System, args: Vec<&str>) -> Result<bool, Error> {
if args.len() <= 0 {
return Ok(true);
}
@ -108,15 +108,15 @@ impl MC68010 {
if args.len() > 1 {
let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?;
let len = if args.len() > 2 { u32::from_str_radix(args[2], 16).map_err(|_| Error::new("Unable to parse length"))? } else { 0x20 };
space.dump_memory(addr as Address, len as Address);
system.dump_memory(addr as Address, len as Address);
} else {
space.dump_memory(self.state.msp as Address, 0x40 as Address);
system.dump_memory(self.state.msp as Address, 0x40 as Address);
}
},
"ds" | "stack" | "dumpstack" => {
println!("Stack:");
for addr in &self.debugger.stack_tracer.calls {
println!(" {:08x}", space.read_beu32(*addr as Address)?);
println!(" {:08x}", system.read_beu32(*addr as Address)?);
}
},
"so" | "stepout" => {

View File

@ -2,7 +2,8 @@
use std::fmt;
use crate::error::Error;
use crate::memory::{Address, Addressable, AddressSpace};
use crate::memory::Address;
use crate::system::{System, DeviceRefMut};
use super::execute::ERR_ILLEGAL_INSTRUCTION;
@ -182,28 +183,31 @@ pub enum Instruction {
pub struct M68kDecoder {
pub base: u32,
pub start: u32,
pub end: u32,
pub instruction: Instruction,
}
impl M68kDecoder {
pub fn new(start: u32) -> M68kDecoder {
pub fn new(base: u32, start: u32) -> M68kDecoder {
M68kDecoder {
base: base,
start: start,
end: start,
instruction: Instruction::NOP,
}
}
pub fn decode_at(space: &mut AddressSpace, start: u32) -> Result<M68kDecoder, Error> {
let mut decoder = M68kDecoder::new(start);
decoder.instruction = decoder.decode_one(space)?;
pub fn decode_at(system: &System, start: u32) -> Result<M68kDecoder, Error> {
let (mut memory, relative_addr) = system.get_device_in_range(start as Address, 12)?;
let mut decoder = M68kDecoder::new(start - relative_addr as u32, start);
decoder.instruction = decoder.decode_one(&mut memory)?;
Ok(decoder)
}
pub fn decode_one(&mut self, space: &mut AddressSpace) -> Result<Instruction, Error> {
let ins = self.read_instruction_word(space)?;
pub fn decode_one(&mut self, system: &mut DeviceRefMut<'_>) -> Result<Instruction, Error> {
let ins = self.read_instruction_word(system)?;
match ((ins & 0xF000) >> 12) as u8 {
OPCG_BIT_OPS => {
@ -212,7 +216,7 @@ impl M68kDecoder {
if (ins & 0x3F) == 0b111100 {
match (ins & 0x00C0) >> 6 {
0b00 => {
let data = self.read_instruction_word(space)?;
let data = self.read_instruction_word(system)?;
match optype {
0b0000 => Ok(Instruction::ORtoCCR(data as u8)),
0b0001 => Ok(Instruction::ANDtoCCR(data as u8)),
@ -221,7 +225,7 @@ impl M68kDecoder {
}
},
0b01 => {
let data = self.read_instruction_word(space)?;
let data = self.read_instruction_word(system)?;
match optype {
0b0000 => Ok(Instruction::ORtoSR(data)),
0b0010 => Ok(Instruction::ANDtoSR(data)),
@ -235,10 +239,10 @@ impl M68kDecoder {
let bitnum = if (ins & 0x0100) == 0x0100 {
Target::DirectDReg(get_high_reg(ins))
} else {
Target::Immediate(self.read_instruction_word(space)? as u32)
Target::Immediate(self.read_instruction_word(system)? as u32)
};
let target = self.decode_lower_effective_address(space, ins, Some(Size::Byte))?;
let target = self.decode_lower_effective_address(system, ins, Some(Size::Byte))?;
let size = match target {
Target::DirectAReg(_) | Target::DirectDReg(_) => Size::Long,
_ => Size::Byte,
@ -255,12 +259,12 @@ impl M68kDecoder {
} else {
let size = get_size(ins);
let data = match size {
Some(Size::Byte) => (self.read_instruction_word(space)? as u32 & 0xFF),
Some(Size::Word) => self.read_instruction_word(space)? as u32,
Some(Size::Long) => self.read_instruction_long(space)?,
Some(Size::Byte) => (self.read_instruction_word(system)? as u32 & 0xFF),
Some(Size::Word) => self.read_instruction_word(system)? as u32,
Some(Size::Long) => self.read_instruction_long(system)?,
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
};
let target = self.decode_lower_effective_address(space, ins, size)?;
let target = self.decode_lower_effective_address(system, ins, size)?;
match optype {
0b0000 => Ok(Instruction::OR(Target::Immediate(data), target, size.unwrap())),
@ -274,13 +278,13 @@ impl M68kDecoder {
}
},
OPCG_MOVE_BYTE => {
let src = self.decode_lower_effective_address(space, ins, Some(Size::Byte))?;
let dest = self.decode_upper_effective_address(space, ins, Some(Size::Byte))?;
let src = self.decode_lower_effective_address(system, ins, Some(Size::Byte))?;
let dest = self.decode_upper_effective_address(system, ins, Some(Size::Byte))?;
Ok(Instruction::MOVE(src, dest, Size::Byte))
},
OPCG_MOVE_LONG => {
let src = self.decode_lower_effective_address(space, ins, Some(Size::Long))?;
let dest = self.decode_upper_effective_address(space, ins, Some(Size::Long))?;
let src = self.decode_lower_effective_address(system, ins, Some(Size::Long))?;
let dest = self.decode_upper_effective_address(system, ins, Some(Size::Long))?;
if let Target::DirectAReg(reg) = dest {
Ok(Instruction::MOVEA(src, reg, Size::Long))
} else {
@ -288,8 +292,8 @@ impl M68kDecoder {
}
},
OPCG_MOVE_WORD => {
let src = self.decode_lower_effective_address(space, ins, Some(Size::Word))?;
let dest = self.decode_upper_effective_address(space, ins, Some(Size::Word))?;
let src = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
let dest = self.decode_upper_effective_address(system, ins, Some(Size::Word))?;
if let Target::DirectAReg(reg) = dest {
Ok(Instruction::MOVEA(src, reg, Size::Word))
} else {
@ -301,11 +305,11 @@ impl M68kDecoder {
// CHK Instruction
panic!("Not Implemented");
} else if (ins & 0b000111000000) == 0b000111000000 {
let src = self.decode_lower_effective_address(space, ins, None)?;
let src = self.decode_lower_effective_address(system, ins, None)?;
let dest = get_high_reg(ins);
Ok(Instruction::LEA(src, dest))
} else if (ins & 0b100000000000) == 0b000000000000 {
let target = self.decode_lower_effective_address(space, ins, Some(Size::Word))?;
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
match (ins & 0x0700) >> 8 {
0b000 => {
match get_size(ins) {
@ -340,8 +344,8 @@ impl M68kDecoder {
if mode == 0b000 {
Ok(Instruction::EXT(get_low_reg(ins), size))
} else {
let data = self.read_instruction_word(space)?;
let target = self.decode_lower_effective_address(space, ins, None)?;
let data = self.read_instruction_word(system)?;
let target = self.decode_lower_effective_address(system, ins, None)?;
let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget };
Ok(Instruction::MOVEM(target, size, dir, data))
}
@ -350,26 +354,26 @@ impl M68kDecoder {
let mode = get_low_mode(ins);
match (subselect, mode) {
(0b000, _) => {
let target = self.decode_lower_effective_address(space, ins, Some(Size::Byte))?;
let target = self.decode_lower_effective_address(system, ins, Some(Size::Byte))?;
Ok(Instruction::NBCD(target))
},
(0b001, 0b000) => {
Ok(Instruction::SWAP(get_low_reg(ins)))
},
(0b001, _) => {
let target = self.decode_lower_effective_address(space, ins, None)?;
let target = self.decode_lower_effective_address(system, ins, None)?;
Ok(Instruction::PEA(target))
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
} else if (ins & 0b111100000000) == 0b101000000000 {
let target = self.decode_lower_effective_address(space, ins, Some(Size::Word))?;
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
match get_size(ins) {
Some(size) => Ok(Instruction::TST(target, size)),
None => Ok(Instruction::TAS(target)),
}
} else if (ins & 0b111110000000) == 0b111010000000 {
let target = self.decode_lower_effective_address(space, ins, None)?;
let target = self.decode_lower_effective_address(system, ins, None)?;
if (ins & 0b01000000) == 0 {
Ok(Instruction::JSR(target))
} else {
@ -380,7 +384,7 @@ impl M68kDecoder {
} else if (ins & 0b111111110000) == 0b111001010000 {
let reg = get_low_reg(ins);
if (ins & 0b1000) == 0 {
let data = self.read_instruction_word(space)?;
let data = self.read_instruction_word(system)?;
Ok(Instruction::LINK(reg, data as i16))
} else {
Ok(Instruction::UNLK(reg))
@ -395,7 +399,7 @@ impl M68kDecoder {
0xE70 => Ok(Instruction::RESET),
0xE71 => Ok(Instruction::NOP),
0xE72 => {
let data = self.read_instruction_word(space)?;
let data = self.read_instruction_word(system)?;
Ok(Instruction::STOP(data))
},
0xE73 => Ok(Instruction::RTE),
@ -404,7 +408,7 @@ impl M68kDecoder {
0xE77 => Ok(Instruction::RTR),
0xE7A | 0xE7B => {
let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget };
let ins2 = self.read_instruction_word(space)?;
let ins2 = self.read_instruction_word(system)?;
let target = match ins2 & 0x8000 {
0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8),
_ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8),
@ -422,7 +426,7 @@ impl M68kDecoder {
OPCG_ADDQ_SUBQ => {
match get_size(ins) {
Some(size) => {
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
let mut data = ((ins & 0x0E00) >> 9) as u32;
if data == 0 {
data = 8;
@ -440,10 +444,10 @@ impl M68kDecoder {
if mode == 0b001 {
let reg = get_low_reg(ins);
let disp = self.read_instruction_word(space)? as i16;
let disp = self.read_instruction_word(system)? as i16;
Ok(Instruction::DBcc(condition, reg, disp))
} else {
let target = self.decode_lower_effective_address(space, ins, Some(Size::Byte))?;
let target = self.decode_lower_effective_address(system, ins, Some(Size::Byte))?;
Ok(Instruction::Scc(condition, target))
}
},
@ -452,7 +456,7 @@ impl M68kDecoder {
OPCG_BRANCH => {
let mut disp = ((ins & 0xFF) as i8) as i16;
if disp == 0 {
disp = self.read_instruction_word(space)? as i16;
disp = self.read_instruction_word(system)? as i16;
}
let condition = get_condition(ins);
match condition {
@ -473,14 +477,14 @@ impl M68kDecoder {
if size.is_none() {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(space, ins, size)?;
let effective_addr = self.decode_lower_effective_address(system, ins, size)?;
Ok(Instruction::DIV(effective_addr, data_reg, Size::Word, sign))
} else if (ins & 0b000111110000) == 0b000100000000 {
// TODO SBCD
panic!("Not Implemented");
} else {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(space, ins, size)?;
let effective_addr = self.decode_lower_effective_address(system, ins, size)?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::OR(from, to, size.unwrap()))
}
@ -492,7 +496,7 @@ impl M68kDecoder {
let size = get_size(ins);
match size {
Some(size) => {
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
if dir == 0 {
Ok(Instruction::SUB(target, Target::DirectDReg(reg), size))
} else {
@ -501,7 +505,7 @@ impl M68kDecoder {
},
None => {
let size = if dir == 0 { Size::Word } else { Size::Long };
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
Ok(Instruction::SUB(target, Target::DirectAReg(reg), size))
},
}
@ -513,16 +517,16 @@ impl M68kDecoder {
match (optype, size) {
(0b1, Some(size)) => {
// TODO need to decode the CMPM instruction (mode == 0b001) (would likely be erroneously decoded atm)
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
Ok(Instruction::EOR(Target::DirectDReg(reg), target, size))
},
(0b0, Some(size)) => {
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
Ok(Instruction::CMP(target, Target::DirectDReg(reg), size))
},
(_, None) => {
let size = if optype == 0 { Size::Word } else { Size::Long };
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
Ok(Instruction::CMPA(target, reg, size))
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
@ -534,14 +538,14 @@ impl M68kDecoder {
if size.is_none() {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(space, ins, Some(Size::Word))?;
let effective_addr = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
Ok(Instruction::MUL(effective_addr, data_reg, Size::Word, sign))
} else if (ins & 0b000111110000) == 0b000100000000 {
// TODO ABCD or EXG
panic!("Not Implemented");
} else {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(space, ins, size)?;
let effective_addr = self.decode_lower_effective_address(system, ins, size)?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::AND(from, to, size.unwrap()))
}
@ -553,7 +557,7 @@ impl M68kDecoder {
let size = get_size(ins);
match size {
Some(size) => {
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
if dir == 0 {
Ok(Instruction::ADD(target, Target::DirectDReg(reg), size))
} else {
@ -562,7 +566,7 @@ impl M68kDecoder {
},
None => {
let size = if dir == 0 { Size::Word } else { Size::Long };
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
Ok(Instruction::ADD(target, Target::DirectAReg(reg), size))
},
}
@ -588,7 +592,7 @@ impl M68kDecoder {
}
},
None => {
let target = self.decode_lower_effective_address(space, ins, Some(Size::Word))?;
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
let count = Target::Immediate(1);
match (ins & 0x0600) >> 9 {
@ -605,30 +609,30 @@ impl M68kDecoder {
}
}
fn read_instruction_word(&mut self, space: &mut AddressSpace) -> Result<u16, Error> {
let word = space.read_beu16(self.end as Address)?;
fn read_instruction_word(&mut self, system: &mut DeviceRefMut<'_>) -> Result<u16, Error> {
let word = system.read_beu16((self.end - self.base) as Address)?;
//debug!("{:#010x} {:#06x?}", self.end, word);
self.end += 2;
Ok(word)
}
fn read_instruction_long(&mut self, space: &mut AddressSpace) -> Result<u32, Error> {
let word = space.read_beu32(self.end as Address)?;
fn read_instruction_long(&mut self, system: &mut DeviceRefMut<'_>) -> Result<u32, Error> {
let word = system.read_beu32((self.end - self.base) as Address)?;
//debug!("{:#010x} {:#010x}", self.end, word);
self.end += 4;
Ok(word)
}
fn decode_lower_effective_address(&mut self, space: &mut AddressSpace, ins: u16, size: Option<Size>) -> Result<Target, Error> {
fn decode_lower_effective_address(&mut self, system: &mut DeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
let reg = get_low_reg(ins);
let mode = get_low_mode(ins);
self.get_mode_as_target(space, mode, reg, size)
self.get_mode_as_target(system, mode, reg, size)
}
fn decode_upper_effective_address(&mut self, space: &mut AddressSpace, ins: u16, size: Option<Size>) -> Result<Target, Error> {
fn decode_upper_effective_address(&mut self, system: &mut DeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
let reg = get_high_reg(ins);
let mode = get_high_mode(ins);
self.get_mode_as_target(space, mode, reg, size)
self.get_mode_as_target(system, mode, reg, size)
}
fn decode_brief_extension_word(&self, brief_extension: u16) -> (RegisterType, u8, i32, Size) {
@ -641,7 +645,7 @@ impl M68kDecoder {
(rtype, xreg, data, size)
}
pub fn get_mode_as_target(&mut self, space: &mut AddressSpace, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
pub fn get_mode_as_target(&mut self, system: &mut DeviceRefMut<'_>, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
let value = match mode {
0b000 => Target::DirectDReg(reg),
0b001 => Target::DirectAReg(reg),
@ -649,37 +653,37 @@ impl M68kDecoder {
0b011 => Target::IndirectARegInc(reg),
0b100 => Target::IndirectARegDec(reg),
0b101 => {
let data = sign_extend_to_long(self.read_instruction_word(space)? as u32, Size::Word);
let data = sign_extend_to_long(self.read_instruction_word(system)? as u32, Size::Word);
Target::IndirectARegOffset(reg, data)
},
0b110 => {
let brief_extension = self.read_instruction_word(space)?;
let brief_extension = self.read_instruction_word(system)?;
let (rtype, xreg, data, size) = self.decode_brief_extension_word(brief_extension);
Target::IndirectARegXRegOffset(reg, rtype, xreg, data, size)
},
0b111 => {
match reg {
0b000 => {
let value = sign_extend_to_long(self.read_instruction_word(space)? as u32, Size::Word) as u32;
let value = sign_extend_to_long(self.read_instruction_word(system)? as u32, Size::Word) as u32;
Target::IndirectMemory(value)
},
0b001 => {
let value = self.read_instruction_long(space)?;
let value = self.read_instruction_long(system)?;
Target::IndirectMemory(value)
},
0b010 => {
let data = sign_extend_to_long(self.read_instruction_word(space)? as u32, Size::Word);
let data = sign_extend_to_long(self.read_instruction_word(system)? as u32, Size::Word);
Target::IndirectPCOffset(data)
},
0b011 => {
let brief_extension = self.read_instruction_word(space)?;
let brief_extension = self.read_instruction_word(system)?;
let (rtype, xreg, data, size) = self.decode_brief_extension_word(brief_extension);
Target::IndirectPCXRegOffset(rtype, xreg, data, size)
},
0b100 => {
let data = match size {
Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(space)? as u32,
Some(Size::Long) => self.read_instruction_long(space)?,
Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(system)? as u32,
Some(Size::Long) => self.read_instruction_long(system)?,
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
};
Target::Immediate(data)

View File

@ -1,7 +1,8 @@
use crate::error::Error;
use crate::timers::CpuTimer;
use crate::memory::{Address, Addressable, AddressSpace};
use crate::memory::Address;
use crate::system::System;
use super::debugger::M68kDebugger;
use super::decode::{
@ -19,14 +20,6 @@ use super::decode::{
};
/*
pub trait Processor {
fn reset();
fn step();
}
*/
const FLAGS_ON_RESET: u16 = 0x2700;
pub const FLAGS_CARRY: u16 = 0x0001;
@ -91,13 +84,13 @@ impl MC68010 {
pub fn new() -> MC68010 {
MC68010 {
state: MC68010State::new(),
decoder: M68kDecoder::new(0),
decoder: M68kDecoder::new(0, 0),
debugger: M68kDebugger::new(),
timer: CpuTimer::new(),
}
}
pub fn dump_state(&self, space: &mut AddressSpace) {
pub fn dump_state(&self, system: &System) {
println!("Status: {:?}", self.state.status);
println!("PC: {:#010x}", self.state.pc);
println!("SR: {:#06x}", self.state.sr);
@ -110,13 +103,13 @@ impl MC68010 {
println!("Current Instruction: {:#010x} {:?}", self.decoder.start, self.decoder.instruction);
println!("");
space.dump_memory(self.state.msp as Address, 0x40);
system.dump_memory(self.state.msp as Address, 0x40);
println!("");
}
pub fn reset(&mut self) {
self.state = MC68010State::new();
self.decoder = M68kDecoder::new(0);
self.decoder = M68kDecoder::new(0, 0);
self.debugger = M68kDebugger::new();
}
@ -124,88 +117,88 @@ impl MC68010 {
self.state.status != Status::Stopped
}
pub fn init(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
pub fn init(&mut self, system: &System) -> Result<(), Error> {
println!("Initializing CPU");
self.state.msp = space.read_beu32(0)?;
self.state.pc = space.read_beu32(4)?;
self.state.msp = system.read_beu32(0)?;
self.state.pc = system.read_beu32(4)?;
self.state.status = Status::Running;
Ok(())
}
pub fn step(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
pub fn step(&mut self, system: &System) -> Result<(), Error> {
match self.state.status {
Status::Init => self.init(space),
Status::Init => self.init(system),
Status::Stopped | Status::Halted => Err(Error::new("CPU stopped")),
Status::Running => {
let timer = self.timer.cycle.start();
self.decode_next(space)?;
self.execute_current(space)?;
self.decode_next(system)?;
self.execute_current(system)?;
self.timer.cycle.end(timer);
//if (self.timer.cycle.events % 500) == 0 {
// println!("{}", self.timer);
//}
if (self.timer.cycle.events % 500) == 0 {
println!("{}", self.timer);
}
Ok(())
},
}
}
pub fn exception(&mut self, space: &mut AddressSpace, number: u8) -> Result<(), Error> {
pub fn exception(&mut self, system: &System, number: u8) -> Result<(), Error> {
let offset = (number as u16) << 2;
self.push_word(space, offset)?;
self.push_long(space, self.state.pc)?;
self.push_word(space, self.state.sr)?;
self.push_word(system, offset)?;
self.push_long(system, self.state.pc)?;
self.push_word(system, self.state.sr)?;
self.state.sr |= FLAGS_SUPERVISOR;
self.state.sr &= !FLAGS_TRACING;
self.state.pc = space.read_beu32((self.state.vbr + offset as u32) as Address)?;
self.state.pc = system.read_beu32((self.state.vbr + offset as u32) as Address)?;
Ok(())
}
pub fn decode_next(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
pub fn decode_next(&mut self, system: &System) -> Result<(), Error> {
self.check_breakpoints();
let timer = self.timer.decode.start();
self.decoder = M68kDecoder::decode_at(space, self.state.pc)?;
self.decoder = M68kDecoder::decode_at(system, self.state.pc)?;
self.timer.decode.end(timer);
if self.debugger.use_tracing {
// Print instruction bytes for debugging
let ins_data: Result<String, Error> =
(0..((self.decoder.end - self.decoder.start) / 2)).map(|offset|
Ok(format!("{:04x} ", space.read_beu16((self.decoder.start + (offset * 2)) as Address)?))
Ok(format!("{:04x} ", system.read_beu16((self.decoder.start + (offset * 2)) as Address)?))
).collect();
debug!("{:#010x}: {}\n\t{:?}\n", self.decoder.start, ins_data?, self.decoder.instruction);
}
if self.debugger.use_debugger {
self.run_debugger(space);
self.run_debugger(system);
}
self.state.pc = self.decoder.end;
Ok(())
}
pub fn execute_current(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
pub fn execute_current(&mut self, system: &System) -> Result<(), Error> {
let timer = self.timer.decode.start();
match self.decoder.instruction {
Instruction::ADD(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
let existing = self.get_target_value(space, dest, size)?;
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
let (result, carry) = overflowing_add_sized(existing, value, size);
match dest {
Target::DirectAReg(_) => { },
_ => self.set_compare_flags(result, size, carry, get_overflow(existing, value, result, size)),
}
self.set_target_value(space, dest, result, size)?;
self.set_target_value(system, dest, result, size)?;
},
Instruction::AND(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
let existing = self.get_target_value(space, dest, size)?;
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
let result = get_value_sized(existing & value, size);
self.set_target_value(space, dest, result, size)?;
self.set_target_value(system, dest, result, size)?;
self.set_logic_flags(result, size);
},
Instruction::ANDtoCCR(value) => {
@ -215,8 +208,8 @@ impl MC68010 {
self.state.sr = self.state.sr | value;
},
Instruction::ASd(count, target, size, shift_dir) => {
let count = self.get_target_value(space, count, size)? % 64;
let mut pair = (self.get_target_value(space, target, size)?, false);
let count = self.get_target_value(system, count, size)? % 64;
let mut pair = (self.get_target_value(system, target, size)?, false);
let original = pair.0;
for _ in 0..count {
pair = shift_operation(pair.0, size, shift_dir, true);
@ -228,7 +221,7 @@ impl MC68010 {
if get_msb(pair.0, size) != get_msb(original, size) {
self.state.sr |= FLAGS_OVERFLOW;
}
self.set_target_value(space, target, pair.0, size)?;
self.set_target_value(system, target, pair.0, size)?;
},
Instruction::Bcc(cond, offset) => {
let should_branch = self.get_current_condition(cond);
@ -240,50 +233,50 @@ impl MC68010 {
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
},
Instruction::BSR(offset) => {
self.push_long(space, self.state.pc)?;
self.push_long(system, self.state.pc)?;
let sp = *self.get_stack_pointer_mut();
self.debugger.stack_tracer.push_return(sp);
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
},
Instruction::BTST(bitnum, target, size) => {
let bitnum = self.get_target_value(space, bitnum, Size::Byte)?;
let value = self.get_target_value(space, target, size)?;
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
let value = self.get_target_value(system, target, size)?;
self.set_bit_test_flags(value, bitnum, size);
},
Instruction::BCHG(bitnum, target, size) => {
let bitnum = self.get_target_value(space, bitnum, Size::Byte)?;
let mut value = self.get_target_value(space, target, size)?;
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
let mut value = self.get_target_value(system, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size);
value = (value & !mask) | (!(value & mask) & mask);
self.set_target_value(space, target, value, size)?;
self.set_target_value(system, target, value, size)?;
},
Instruction::BCLR(bitnum, target, size) => {
let bitnum = self.get_target_value(space, bitnum, Size::Byte)?;
let mut value = self.get_target_value(space, target, size)?;
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
let mut value = self.get_target_value(system, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size);
value = value & !mask;
self.set_target_value(space, target, value, size)?;
self.set_target_value(system, target, value, size)?;
},
Instruction::BSET(bitnum, target, size) => {
let bitnum = self.get_target_value(space, bitnum, Size::Byte)?;
let mut value = self.get_target_value(space, target, size)?;
let bitnum = self.get_target_value(system, bitnum, Size::Byte)?;
let mut value = self.get_target_value(system, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size);
value = value | mask;
self.set_target_value(space, target, value, size)?;
self.set_target_value(system, target, value, size)?;
},
Instruction::CLR(target, size) => {
self.set_target_value(space, target, 0, size)?;
self.set_target_value(system, target, 0, size)?;
// Clear flags except Zero flag
self.state.sr = (self.state.sr & 0xFFF0) | FLAGS_ZERO;
},
Instruction::CMP(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
let existing = self.get_target_value(space, dest, size)?;
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
let (result, carry) = overflowing_sub_sized(existing, value, size);
self.set_compare_flags(result, size, carry, get_overflow(existing, value, result, size));
},
Instruction::CMPA(src, reg, size) => {
let value = sign_extend_to_long(self.get_target_value(space, src, size)?, size) as u32;
let value = sign_extend_to_long(self.get_target_value(system, src, size)?, size) as u32;
let existing = *self.get_a_reg_mut(reg);
let (result, carry) = overflowing_sub_sized(existing, value, Size::Long);
self.set_compare_flags(result, Size::Long, carry, get_overflow(existing, value, result, Size::Long));
@ -303,19 +296,19 @@ impl MC68010 {
return Err(Error::new("Unsupported multiplication size"));
}
let value = self.get_target_value(space, src, size)?;
let existing = self.get_target_value(space, dest, Size::Long)?;
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, Size::Long)?;
let result = match sign {
Sign::Signed => ((existing as i16 % value as i16) as u32) << 16 | (0xFFFF & (existing as i16 / value as i16) as u32),
Sign::Unsigned => ((existing as u16 % value as u16) as u32) << 16 | (0xFFFF & (existing as u16 / value as u16) as u32),
};
self.set_target_value(space, dest, result, Size::Long)?;
self.set_target_value(system, dest, result, Size::Long)?;
},
Instruction::EOR(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
let existing = self.get_target_value(space, dest, size)?;
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
let result = get_value_sized(existing ^ value, size);
self.set_target_value(space, dest, result, size)?;
self.set_target_value(system, dest, result, size)?;
self.set_logic_flags(result, size);
},
Instruction::EORtoCCR(value) => {
@ -342,7 +335,7 @@ impl MC68010 {
self.state.pc = self.get_target_address(target)?;
},
Instruction::JSR(target) => {
self.push_long(space, self.state.pc)?;
self.push_long(system, self.state.pc)?;
let sp = *self.get_stack_pointer_mut();
self.debugger.stack_tracer.push_return(sp);
self.state.pc = self.get_target_address(target)?;
@ -354,15 +347,15 @@ impl MC68010 {
},
Instruction::LINK(reg, offset) => {
let value = *self.get_a_reg_mut(reg);
self.push_long(space, value)?;
self.push_long(system, value)?;
let sp = *self.get_stack_pointer_mut();
let addr = self.get_a_reg_mut(reg);
*addr = sp;
*self.get_stack_pointer_mut() = sp.wrapping_add((offset as i32) as u32);
},
Instruction::LSd(count, target, size, shift_dir) => {
let count = self.get_target_value(space, count, size)? % 64;
let mut pair = (self.get_target_value(space, target, size)?, false);
let count = self.get_target_value(system, count, size)? % 64;
let mut pair = (self.get_target_value(system, target, size)?, false);
for _ in 0..count {
pair = shift_operation(pair.0, size, shift_dir, false);
}
@ -370,47 +363,47 @@ impl MC68010 {
if pair.1 {
self.state.sr |= FLAGS_EXTEND | FLAGS_CARRY;
}
self.set_target_value(space, target, pair.0, size)?;
self.set_target_value(system, target, pair.0, size)?;
},
Instruction::MOVE(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
let value = self.get_target_value(system, src, size)?;
self.set_logic_flags(value, size);
self.set_target_value(space, dest, value, size)?;
self.set_target_value(system, dest, value, size)?;
},
Instruction::MOVEA(src, reg, size) => {
let value = self.get_target_value(space, src, size)?;
let value = self.get_target_value(system, src, size)?;
let value = sign_extend_to_long(value, size) as u32;
let addr = self.get_a_reg_mut(reg);
*addr = value;
},
Instruction::MOVEfromSR(target) => {
self.set_target_value(space, target, self.state.sr as u32, Size::Word)?;
self.set_target_value(system, target, self.state.sr as u32, Size::Word)?;
},
Instruction::MOVEtoSR(target) => {
self.state.sr = self.get_target_value(space, target, Size::Word)? as u16;
self.state.sr = self.get_target_value(system, target, Size::Word)? as u16;
},
Instruction::MOVEtoCCR(target) => {
let value = self.get_target_value(space, target, Size::Word)? as u16;
let value = self.get_target_value(system, target, Size::Word)? as u16;
self.state.sr = (self.state.sr & 0xFF00) | (value & 0x00FF);
},
Instruction::MOVEC(target, control_reg, dir) => {
match dir {
Direction::FromTarget => {
let value = self.get_target_value(space, target, Size::Long)?;
let value = self.get_target_value(system, target, Size::Long)?;
let addr = self.get_control_reg_mut(control_reg);
*addr = value;
},
Direction::ToTarget => {
let addr = self.get_control_reg_mut(control_reg);
let value = *addr;
self.set_target_value(space, target, value, Size::Long)?;
self.set_target_value(system, target, value, Size::Long)?;
},
}
},
Instruction::MOVEUSP(target, dir) => {
match dir {
Direction::ToTarget => self.set_target_value(space, target, self.state.usp, Size::Long)?,
Direction::FromTarget => { self.state.usp = self.get_target_value(space, target, Size::Long)?; },
Direction::ToTarget => self.set_target_value(system, target, self.state.usp, Size::Long)?,
Direction::FromTarget => { self.state.usp = self.get_target_value(system, target, Size::Long)?; },
}
},
Instruction::MOVEM(target, size, dir, mask) => {
@ -424,14 +417,14 @@ impl MC68010 {
if (mask & 0x01) != 0 {
let value = *self.get_a_reg_mut(i);
addr -= size.in_bytes();
set_address_sized(space, addr as Address, value, size);
set_address_sized(system, addr as Address, value, size)?;
}
mask >>= 1;
}
for i in (0..8).rev() {
if (mask & 0x01) != 0 {
addr -= size.in_bytes();
set_address_sized(space, addr as Address, self.state.d_reg[i], size);
set_address_sized(system, addr as Address, self.state.d_reg[i], size)?;
}
mask >>= 1;
}
@ -439,14 +432,14 @@ impl MC68010 {
let mut mask = mask;
for i in 0..8 {
if (mask & 0x01) != 0 {
self.state.d_reg[i] = get_address_sized(space, addr as Address, size)?;
self.state.d_reg[i] = get_address_sized(system, addr as Address, size)?;
addr += size.in_bytes();
}
mask >>= 1;
}
for i in 0..8 {
if (mask & 0x01) != 0 {
*self.get_a_reg_mut(i) = get_address_sized(space, addr as Address, size)?;
*self.get_a_reg_mut(i) = get_address_sized(system, addr as Address, size)?;
addr += size.in_bytes();
}
mask >>= 1;
@ -472,36 +465,36 @@ impl MC68010 {
return Err(Error::new("Unsupported multiplication size"));
}
let value = self.get_target_value(space, src, size)?;
let existing = self.get_target_value(space, dest, size)?;
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
let result = match sign {
Sign::Signed => (sign_extend_to_long(existing, Size::Word) * sign_extend_to_long(value, Size::Word)) as u32,
Sign::Unsigned => existing as u32 * value as u32,
};
self.set_target_value(space, dest, result, Size::Long)?;
self.set_target_value(system, dest, result, Size::Long)?;
},
//Instruction::NBCD(Target) => {
//},
Instruction::NEG(target, size) => {
let original = self.get_target_value(space, target, size)?;
let original = self.get_target_value(system, target, size)?;
let (value, _) = (0 as u32).overflowing_sub(original);
self.set_target_value(space, target, value, size);
self.set_target_value(system, target, value, size)?;
self.set_compare_flags(value, size, value != 0, get_overflow(0, original, value, size));
},
//Instruction::NEGX(Target, Size) => {
//},
Instruction::NOP => { },
Instruction::NOT(target, size) => {
let mut value = self.get_target_value(space, target, size)?;
let mut value = self.get_target_value(system, target, size)?;
value = get_value_sized(!value, size);
self.set_target_value(space, target, value, size)?;
self.set_target_value(system, target, value, size)?;
self.set_logic_flags(value, size);
},
Instruction::OR(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
let existing = self.get_target_value(space, dest, size)?;
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
let result = get_value_sized(existing | value, size);
self.set_target_value(space, dest, result, size)?;
self.set_target_value(system, dest, result, size)?;
self.set_logic_flags(result, size);
},
Instruction::ORtoCCR(value) => {
@ -512,13 +505,13 @@ impl MC68010 {
},
Instruction::PEA(target) => {
let value = self.get_target_address(target)?;
self.push_long(space, value)?;
self.push_long(system, value)?;
},
//Instruction::RESET => {
//},
Instruction::ROd(count, target, size, shift_dir) => {
let count = self.get_target_value(space, count, size)? % 64;
let mut pair = (self.get_target_value(space, target, size)?, false);
let count = self.get_target_value(system, count, size)? % 64;
let mut pair = (self.get_target_value(system, target, size)?, false);
for _ in 0..count {
pair = rotate_operation(pair.0, size, shift_dir);
}
@ -526,27 +519,27 @@ impl MC68010 {
if pair.1 {
self.state.sr |= FLAGS_CARRY;
}
self.set_target_value(space, target, pair.0, size)?;
self.set_target_value(system, target, pair.0, size)?;
},
//Instruction::ROXd(Target, Target, Size, ShiftDirection) => {
//},
Instruction::RTE => {
self.state.sr = self.pop_word(space)?;
self.state.pc = self.pop_long(space)?;
let _ = self.pop_word(space)?;
self.state.sr = self.pop_word(system)?;
self.state.pc = self.pop_long(system)?;
let _ = self.pop_word(system)?;
},
//Instruction::RTR => {
//},
Instruction::RTS => {
self.debugger.stack_tracer.pop_return();
self.state.pc = self.pop_long(space)?;
self.state.pc = self.pop_long(system)?;
},
Instruction::Scc(cond, target) => {
let condition_true = self.get_current_condition(cond);
if condition_true {
self.set_target_value(space, target, 0xFF, Size::Byte);
self.set_target_value(system, target, 0xFF, Size::Byte)?;
} else {
self.set_target_value(space, target, 0x00, Size::Byte);
self.set_target_value(system, target, 0x00, Size::Byte)?;
}
},
Instruction::STOP(flags) => {
@ -554,14 +547,14 @@ impl MC68010 {
self.state.status = Status::Stopped;
},
Instruction::SUB(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
let existing = self.get_target_value(space, dest, size)?;
let value = self.get_target_value(system, src, size)?;
let existing = self.get_target_value(system, dest, size)?;
let (result, carry) = overflowing_sub_sized(existing, value, size);
match dest {
Target::DirectAReg(_) => { },
_ => self.set_compare_flags(result, size, carry, get_overflow(existing, value, result, size)),
}
self.set_target_value(space, dest, result, size)?;
self.set_target_value(system, dest, result, size)?;
},
Instruction::SWAP(reg) => {
let value = self.state.d_reg[reg as usize];
@ -570,21 +563,21 @@ impl MC68010 {
//Instruction::TAS(Target) => {
//},
Instruction::TST(target, size) => {
let value = self.get_target_value(space, target, size)?;
let value = self.get_target_value(system, target, size)?;
self.set_logic_flags(value, size);
},
Instruction::TRAP(number) => {
self.exception(space, 32 + number)?;
self.exception(system, 32 + number)?;
},
Instruction::TRAPV => {
if self.get_flag(FLAGS_OVERFLOW) {
self.exception(space, 7)?;
self.exception(system, 7)?;
}
},
Instruction::UNLK(reg) => {
let value = *self.get_a_reg_mut(reg);
*self.get_stack_pointer_mut() = value;
let new_value = self.pop_long(space)?;
let new_value = self.pop_long(system)?;
let addr = self.get_a_reg_mut(reg);
*addr = new_value;
},
@ -595,72 +588,72 @@ impl MC68010 {
Ok(())
}
fn push_word(&mut self, space: &mut AddressSpace, value: u16) -> Result<(), Error> {
fn push_word(&mut self, system: &System, value: u16) -> Result<(), Error> {
let reg = self.get_stack_pointer_mut();
*reg -= 2;
space.write_beu16(*reg as Address, value)
system.write_beu16(*reg as Address, value)
}
fn pop_word(&mut self, space: &mut AddressSpace) -> Result<u16, Error> {
fn pop_word(&mut self, system: &System) -> Result<u16, Error> {
let reg = self.get_stack_pointer_mut();
let value = space.read_beu16(*reg as Address)?;
let value = system.read_beu16(*reg as Address)?;
*reg += 2;
Ok(value)
}
fn push_long(&mut self, space: &mut AddressSpace, value: u32) -> Result<(), Error> {
fn push_long(&mut self, system: &System, value: u32) -> Result<(), Error> {
let reg = self.get_stack_pointer_mut();
*reg -= 4;
space.write_beu32(*reg as Address, value)
system.write_beu32(*reg as Address, value)
}
fn pop_long(&mut self, space: &mut AddressSpace) -> Result<u32, Error> {
fn pop_long(&mut self, system: &System) -> Result<u32, Error> {
let reg = self.get_stack_pointer_mut();
let value = space.read_beu32(*reg as Address)?;
let value = system.read_beu32(*reg as Address)?;
*reg += 4;
Ok(value)
}
pub fn get_target_value(&mut self, space: &mut AddressSpace, target: Target, size: Size) -> Result<u32, Error> {
pub fn get_target_value(&mut self, system: &System, target: Target, size: Size) -> Result<u32, Error> {
match target {
Target::Immediate(value) => Ok(value),
Target::DirectDReg(reg) => Ok(get_value_sized(self.state.d_reg[reg as usize], size)),
Target::DirectAReg(reg) => Ok(get_value_sized(*self.get_a_reg_mut(reg), size)),
Target::IndirectAReg(reg) => get_address_sized(space, *self.get_a_reg_mut(reg) as Address, size),
Target::IndirectAReg(reg) => get_address_sized(system, *self.get_a_reg_mut(reg) as Address, size),
Target::IndirectARegInc(reg) => {
let addr = self.get_a_reg_mut(reg);
let result = get_address_sized(space, *addr as Address, size);
let result = get_address_sized(system, *addr as Address, size);
*addr += size.in_bytes();
result
},
Target::IndirectARegDec(reg) => {
let addr = self.get_a_reg_mut(reg);
*addr -= size.in_bytes();
get_address_sized(space, *addr as Address, size)
get_address_sized(system, *addr as Address, size)
},
Target::IndirectARegOffset(reg, offset) => {
let addr = self.get_a_reg_mut(reg);
get_address_sized(space, (*addr).wrapping_add(offset as u32) as Address, size)
get_address_sized(system, (*addr).wrapping_add(offset as u32) as Address, size)
},
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size);
let addr = self.get_a_reg_mut(reg);
get_address_sized(space, (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, size)
get_address_sized(system, (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, size)
},
Target::IndirectMemory(addr) => {
get_address_sized(space, addr as Address, size)
get_address_sized(system, addr as Address, size)
},
Target::IndirectPCOffset(offset) => {
get_address_sized(space, (self.decoder.start + 2).wrapping_add(offset as u32) as Address, size)
get_address_sized(system, (self.decoder.start + 2).wrapping_add(offset as u32) as Address, size)
},
Target::IndirectPCXRegOffset(rtype, xreg, offset, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size);
get_address_sized(space, (self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, size)
get_address_sized(system, (self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, size)
},
}
}
pub fn set_target_value(&mut self, space: &mut AddressSpace, target: Target, value: u32, size: Size) -> Result<(), Error> {
pub fn set_target_value(&mut self, system: &System, target: Target, value: u32, size: Size) -> Result<(), Error> {
match target {
Target::DirectDReg(reg) => {
set_value_sized(&mut self.state.d_reg[reg as usize], value, size);
@ -669,29 +662,29 @@ impl MC68010 {
set_value_sized(self.get_a_reg_mut(reg), value, size);
},
Target::IndirectAReg(reg) => {
set_address_sized(space, *self.get_a_reg_mut(reg) as Address, value, size)?;
set_address_sized(system, *self.get_a_reg_mut(reg) as Address, value, size)?;
},
Target::IndirectARegInc(reg) => {
let addr = self.get_a_reg_mut(reg);
set_address_sized(space, *addr as Address, value, size)?;
set_address_sized(system, *addr as Address, value, size)?;
*addr += size.in_bytes();
},
Target::IndirectARegDec(reg) => {
let addr = self.get_a_reg_mut(reg);
*addr -= size.in_bytes();
set_address_sized(space, *addr as Address, value, size)?;
set_address_sized(system, *addr as Address, value, size)?;
},
Target::IndirectARegOffset(reg, offset) => {
let addr = self.get_a_reg_mut(reg);
set_address_sized(space, (*addr).wrapping_add(offset as u32) as Address, value, size)?;
set_address_sized(system, (*addr).wrapping_add(offset as u32) as Address, value, size)?;
},
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size);
let addr = self.get_a_reg_mut(reg);
set_address_sized(space, (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, value, size)?;
set_address_sized(system, (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, value, size)?;
},
Target::IndirectMemory(addr) => {
set_address_sized(space, addr as Address, value, size)?;
set_address_sized(system, addr as Address, value, size)?;
},
_ => return Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))),
}
@ -907,11 +900,11 @@ fn get_value_sized(value: u32, size: Size) -> u32 {
}
}
fn get_address_sized(space: &mut AddressSpace, addr: Address, size: Size) -> Result<u32, Error> {
fn get_address_sized(system: &System, addr: Address, size: Size) -> Result<u32, Error> {
match size {
Size::Byte => space.read_u8(addr).map(|value| value as u32),
Size::Word => space.read_beu16(addr).map(|value| value as u32),
Size::Long => space.read_beu32(addr),
Size::Byte => system.read_u8(addr).map(|value| value as u32),
Size::Word => system.read_beu16(addr).map(|value| value as u32),
Size::Long => system.read_beu32(addr),
}
}
@ -923,11 +916,11 @@ fn set_value_sized(addr: &mut u32, value: u32, size: Size) {
}
}
fn set_address_sized(space: &mut AddressSpace, addr: Address, value: u32, size: Size) -> Result<(), Error> {
fn set_address_sized(system: &System, addr: Address, value: u32, size: Size) -> Result<(), Error> {
match size {
Size::Byte => space.write_u8(addr, value as u8),
Size::Word => space.write_beu16(addr, value as u16),
Size::Long => space.write_beu32(addr, value),
Size::Byte => system.write_u8(addr, value as u8),
Size::Word => system.write_beu16(addr, value as u16),
Size::Long => system.write_beu32(addr, value),
}
}

View File

@ -1,178 +1,179 @@
use crate::memory::{Address, Addressable, AddressSpace, MemoryBlock};
use crate::memory::{Address, MemoryBlock};
use crate::system::System;
use super::execute::MC68010;
use super::decode::{Instruction, Target, Size, Sign, ShiftDirection};
use super::decode::Instruction;
const INIT_STACK: Address = 0x00002000;
const INIT_ADDR: Address = 0x00000010;
fn init_test() -> (MC68010, AddressSpace) {
let mut space = AddressSpace::new();
fn init_test() -> (MC68010, System) {
let mut system = System::new();
// Insert basic initialization
let mut data = vec![0; 0x00100000];
let data = vec![0; 0x00100000];
let mem = MemoryBlock::new(data);
space.insert(0x00000000, Box::new(mem));
space.write_beu32(0, INIT_STACK as u32).unwrap();
space.write_beu32(4, INIT_ADDR as u32).unwrap();
system.add_device(0x00000000, Box::new(mem)).unwrap();
system.write_beu32(0, INIT_STACK as u32).unwrap();
system.write_beu32(4, INIT_ADDR as u32).unwrap();
let mut cpu = MC68010::new();
cpu.step(&mut space).unwrap();
cpu.step(&system).unwrap();
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
assert_eq!(cpu.state.msp, INIT_STACK as u32);
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
(cpu, space)
(cpu, system)
}
#[cfg(test)]
mod tests {
use crate::memory::{Address, Addressable};
use super::{init_test, INIT_ADDR};
use super::{Instruction, Target, Size, Sign, ShiftDirection};
use crate::memory::{Address, Addressable};
use super::super::decode::{Instruction, Target, Size, Sign, ShiftDirection};
#[test]
fn instruction_nop() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0x4e71).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0x4e71).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
// TODO you need a way to easily check the entire state (you maybe need to make a special struct for the state)
}
#[test]
fn instruction_ori() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0x0008).unwrap();
space.write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0x0008).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::OR(Target::Immediate(0xFF), Target::DirectAReg(0), Size::Byte));
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.a_reg[0], 0x000000FF);
}
#[test]
fn instruction_cmpi_equal() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0x7020).unwrap();
space.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
space.write_beu16(INIT_ADDR + 4, 0x0020).unwrap();
cpu.step(&mut space).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.write_beu16(INIT_ADDR + 4, 0x0020).unwrap();
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x20), Target::DirectDReg(0), Size::Byte));
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x04);
}
#[test]
fn instruction_cmpi_greater() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0x7020).unwrap();
space.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
space.write_beu16(INIT_ADDR + 4, 0x0030).unwrap();
cpu.step(&mut space).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.write_beu16(INIT_ADDR + 4, 0x0030).unwrap();
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte));
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x009);
}
#[test]
fn instruction_cmpi_less() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0x7020).unwrap();
space.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
space.write_beu16(INIT_ADDR + 4, 0x0010).unwrap();
cpu.step(&mut space).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.write_beu16(INIT_ADDR + 4, 0x0010).unwrap();
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x10), Target::DirectDReg(0), Size::Byte));
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x00);
}
#[test]
fn instruction_andi_sr() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0x027C).unwrap();
space.write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0x027C).unwrap();
system.write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoSR(0xF8FF));
//cpu.execute_current(&mut space).unwrap();
//cpu.execute_current(&system).unwrap();
//assert_eq!(cpu.state.sr & 0x0F, 0x00);
}
#[test]
fn instruction_muls() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0xC1FC).unwrap();
space.write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0xC1FC).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed));
//cpu.execute_current(&mut space).unwrap();
//cpu.execute_current(&system).unwrap();
//assert_eq!(cpu.state.sr & 0x0F, 0x00);
}
#[test]
fn instruction_asli() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0xE300).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0xE300).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
cpu.state.d_reg[0] = 0x01;
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000002);
assert_eq!(cpu.state.sr & 0x1F, 0x00);
}
#[test]
fn instruction_asri() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0xE200).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0xE200).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
cpu.state.d_reg[0] = 0x81;
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x000000C0);
assert_eq!(cpu.state.sr & 0x1F, 0x19);
}
#[test]
fn instruction_roli() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0xE318).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0xE318).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
cpu.state.d_reg[0] = 0x80;
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000001);
assert_eq!(cpu.state.sr & 0x1F, 0x01);
}
#[test]
fn instruction_rori() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
space.write_beu16(INIT_ADDR, 0xE218).unwrap();
cpu.decode_next(&mut space).unwrap();
system.write_beu16(INIT_ADDR, 0xE218).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
cpu.state.d_reg[0] = 0x01;
cpu.execute_current(&mut space).unwrap();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000080);
assert_eq!(cpu.state.sr & 0x1F, 0x09);
}
@ -183,83 +184,83 @@ mod tests {
#[test]
fn target_value_direct_d() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
let size = Size::Word;
let expected = 0x1234;
let target = cpu.decoder.get_mode_as_target(&mut space, 0b000, 0b001, Some(size)).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b000, 0b001, Some(size)).unwrap();
assert_eq!(target, Target::DirectDReg(1));
cpu.state.d_reg[1] = expected;
let result = cpu.get_target_value(&mut space, target, size).unwrap();
let result = cpu.get_target_value(&system, target, size).unwrap();
assert_eq!(result, expected);
}
#[test]
fn target_value_direct_a() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
let size = Size::Word;
let expected = 0x1234;
let target = cpu.decoder.get_mode_as_target(&mut space, 0b001, 0b010, Some(size)).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b001, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::DirectAReg(2));
cpu.state.a_reg[2] = expected;
let result = cpu.get_target_value(&mut space, target, size).unwrap();
let result = cpu.get_target_value(&system, target, size).unwrap();
assert_eq!(result, expected);
}
#[test]
fn target_value_indirect_a() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
let size = Size::Long;
let expected_addr = INIT_ADDR;
let expected = 0x12345678;
space.write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&mut space, 0b010, 0b010, Some(size)).unwrap();
system.write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b010, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectAReg(2));
cpu.state.a_reg[2] = INIT_ADDR as u32;
let result = cpu.get_target_value(&mut space, target, size).unwrap();
let result = cpu.get_target_value(&system, target, size).unwrap();
assert_eq!(result, expected);
}
#[test]
fn target_value_indirect_a_inc() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
let size = Size::Long;
let expected_addr = INIT_ADDR;
let expected = 0x12345678;
space.write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&mut space, 0b011, 0b010, Some(size)).unwrap();
system.write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b011, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegInc(2));
cpu.state.a_reg[2] = INIT_ADDR as u32;
let result = cpu.get_target_value(&mut space, target, size).unwrap();
let result = cpu.get_target_value(&system, target, size).unwrap();
assert_eq!(result, expected);
assert_eq!(cpu.state.a_reg[2], (INIT_ADDR as u32) + 4);
}
#[test]
fn target_value_indirect_a_dec() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
let size = Size::Long;
let expected_addr = INIT_ADDR + 4;
let expected = 0x12345678;
space.write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&mut space, 0b100, 0b010, Some(size)).unwrap();
system.write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b100, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegDec(2));
cpu.state.a_reg[2] = (INIT_ADDR as u32) + 4;
let result = cpu.get_target_value(&mut space, target, size).unwrap();
let result = cpu.get_target_value(&system, target, size).unwrap();
assert_eq!(result, expected);
assert_eq!(cpu.state.a_reg[2], INIT_ADDR as u32);
}
@ -267,16 +268,16 @@ mod tests {
#[test]
fn target_value_immediate() {
let (mut cpu, mut space) = init_test();
let (mut cpu, mut system) = init_test();
let size = Size::Word;
let expected = 0x1234;
space.write_beu16(cpu.decoder.end as Address, expected as u16).unwrap();
let target = cpu.decoder.get_mode_as_target(&mut space, 0b111, 0b100, Some(size)).unwrap();
system.write_beu16(cpu.decoder.end as Address, expected as u16).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b111, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::Immediate(expected));
let result = cpu.get_target_value(&mut space, target, size).unwrap();
let result = cpu.get_target_value(&system, target, size).unwrap();
assert_eq!(result, expected);
}
}

View File

@ -4,32 +4,36 @@ mod error;
mod memory;
mod timers;
mod cpus;
mod devices;
mod peripherals;
mod system;
use crate::memory::{AddressSpace, MemoryBlock};
use crate::memory::MemoryBlock;
use crate::cpus::m68k::MC68010;
use crate::devices::mc68681::MC68681;
use crate::devices::ata::AtaDevice;
use crate::peripherals::ata::AtaDevice;
use crate::peripherals::mc68681::MC68681;
use crate::system::{System};
fn main() {
let mut space = AddressSpace::new();
let mut system = System::new();
let monitor = MemoryBlock::load("binaries/monitor.bin").unwrap();
for byte in monitor.contents.iter() {
print!("{:02x} ", byte);
}
space.insert(0x00000000, Box::new(monitor));
system.add_device(0x00000000, Box::new(monitor)).unwrap();
let mut ram = MemoryBlock::new(vec![0; 0x00100000]);
ram.load_at(0, "binaries/kernel.bin").unwrap();
space.insert(0x00100000, Box::new(ram));
system.add_device(0x00100000, Box::new(ram)).unwrap();
let mut ata = AtaDevice::new();
ata.load("binaries/disk-with-partition-table.img").unwrap();
space.insert(0x00600000, Box::new(ata));
system.add_device(0x00600000, Box::new(ata)).unwrap();
let mut serial = MC68681::new();
serial.open().unwrap();
space.insert(0x00700000, Box::new(serial));
system.add_device(0x00700000, Box::new(serial)).unwrap();
let mut cpu = MC68010::new();
@ -37,13 +41,14 @@ fn main() {
//cpu.add_breakpoint(0x0c94);
//cpu.add_breakpoint(0x103234);
//cpu.add_breakpoint(0x224);
//cpu.add_breakpoint(0x10407e);
//cpu.add_breakpoint(0x100334);
while cpu.is_running() {
match cpu.step(&mut space) {
system.step().unwrap();
match cpu.step(&system) {
Ok(()) => { },
Err(err) => {
cpu.dump_state(&mut space);
cpu.dump_state(&system);
panic!("{:?}", err);
},
}

View File

@ -1,8 +1,8 @@
use std::fs;
use std::slice::Iter;
use crate::error::Error;
use crate::system::{Clock, DeviceNumber, Device, System};
pub type Address = u64;
@ -91,104 +91,61 @@ impl Addressable for MemoryBlock {
}
}
impl Device for MemoryBlock {
fn step(&mut self, _system: &System) -> Result<Clock, Error> {
Ok(1)
}
}
pub struct Segment {
pub struct Block {
pub base: Address,
pub contents: Box<dyn Addressable>,
pub length: usize,
pub dev: DeviceNumber,
}
impl Segment {
pub fn new(base: Address, contents: Box<dyn Addressable>) -> Segment {
Segment {
base,
contents,
}
}
pub struct Bus {
pub blocks: Vec<Block>,
}
pub struct AddressSpace {
pub segments: Vec<Segment>,
}
impl AddressSpace {
pub fn new() -> AddressSpace {
AddressSpace {
segments: vec!(),
impl Bus {
pub fn new() -> Bus {
Bus {
blocks: 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);
pub fn insert(&mut self, base: Address, length: usize, dev: DeviceNumber) {
let block = Block { base, length, dev };
for i in 0..self.blocks.len() {
if self.blocks[i].base > block.base {
self.blocks.insert(i, block);
return;
}
}
self.segments.insert(0, seg);
self.blocks.insert(0, block);
}
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;
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(DeviceNumber, Address), Error> {
for block in &self.blocks {
if addr >= block.base && addr <= (block.base + block.length as Address) {
let relative_addr = addr - block.base;
if relative_addr as usize + count <= block.length {
return Ok((block.dev, relative_addr));
} else {
return Err(Error::new(&format!("Error reading address {:#010x}", addr)));
}
line += &format!("{:#06x} ", word.unwrap());
addr += 2;
count -= 2;
}
println!("{}", line);
}
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
}
pub fn max_address(&self) -> Address {
let block = &self.blocks[self.blocks.len() - 1];
block.base + block.length as Address
}
}
impl Addressable for AddressSpace {
fn len(&self) -> usize {
let seg = &self.segments[self.segments.len() - 1];
(seg.base as usize) + seg.contents.len()
}
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
let mut seg = self.get_segment_mut(addr)?;
let relative_addr = addr - seg.base;
if relative_addr as usize + count > seg.contents.len() {
Err(Error::new(&format!("Error reading address {:#010x}", addr)))
} else {
seg.contents.read(relative_addr, count)
}
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
let seg = self.get_segment_mut(addr)?;
seg.contents.write(addr - seg.base, data)
}
}
#[inline(always)]
pub fn read_beu16(data: &[u8]) -> u16 {
@ -221,3 +178,4 @@ pub fn write_beu32(value: u32) -> [u8; 4] {
value as u8,
]
}

View File

@ -3,6 +3,7 @@ use std::fs;
use crate::error::Error;
use crate::memory::{Address, Addressable};
use crate::system::{Clock, Device, System};
const ATA_REG_DEV_CONTROL: Address = 0x1D;
@ -90,7 +91,7 @@ println!(">> {:x}", data[0]);
Ok(data)
}
fn write(&mut self, mut addr: Address, data: &[u8]) -> Result<(), Error> {
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
println!("{}: write to register {:x} with {:x}", DEV_NAME, addr, data[0]);
match addr {
ATA_REG_DRIVE_HEAD => { self.selected_sector |= ((data[0] & 0x1F) as u32) << 24; },
@ -110,7 +111,7 @@ println!(">> {:x}", data[0]);
ATA_REG_FEATURE => {
// TODO implement features
},
ATA_REG_DATA => {
ATA_REG_DATA_BYTE => {
// TODO implement writing
},
_ => { println!("{}: writing {:0x} to {:0x}", DEV_NAME, data[0], addr); },
@ -119,3 +120,9 @@ println!(">> {:x}", data[0]);
}
}
impl Device for AtaDevice {
fn step(&mut self, _system: &System) -> Result<Clock, Error> {
Ok(1)
}
}

View File

@ -1,16 +1,15 @@
use std::slice::Iter;
use std::process::Command;
use std::io::{Read, Write};
use std::os::unix::io::{RawFd, AsRawFd};
use std::os::unix::io::AsRawFd;
use nix::pty::{self, PtyMaster};
use nix::fcntl::OFlag;
use nix::unistd::sleep;
use nix::poll::{poll, PollFd, PollFlags};
use nix::fcntl::{fcntl, FcntlArg};
use crate::error::Error;
use crate::system::{Clock, Device, System};
use crate::memory::{Address, Addressable};
@ -86,7 +85,7 @@ impl MC68681 {
}
}
pub fn step(&mut self) -> Result<(), Error> {
pub fn step_internal(&mut self, _system: &System) -> Result<(), Error> {
if !self.rx_ready() && self.tty.is_some() {
let mut buf = [0; 1];
let tty = self.tty.as_mut().unwrap();
@ -120,7 +119,7 @@ impl Addressable for MC68681 {
let mut data = vec![0; count];
// TODO this is temporary
self.step();
//self.step();
match addr {
REG_SRA_RD => {
@ -136,7 +135,7 @@ impl Addressable for MC68681 {
Ok(data)
}
fn write(&mut self, mut addr: Address, data: &[u8]) -> Result<(), Error> {
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
match addr {
REG_TBA_WR => {
println!("{}: {}", DEV_NAME, data[0] as char);
@ -148,3 +147,10 @@ impl Addressable for MC68681 {
}
}
impl Device for MC68681 {
fn step(&mut self, system: &System) -> Result<Clock, Error> {
self.step_internal(system)?;
Ok(1)
}
}

116
src/system.rs Normal file
View File

@ -0,0 +1,116 @@
use std::cell::{RefCell, RefMut};
use crate::error::Error;
use crate::memory::{self, Address, Addressable, Bus};
pub type Clock = u64;
pub type DeviceNumber = u8;
pub type DeviceRefMut<'a> = RefMut<'a, Box<dyn AddressableDevice>>;
pub trait Device: Addressable {
fn step(&mut self, system: &System) -> Result<Clock, Error>;
}
pub trait AddressableDevice: Device + Addressable { }
impl<T: Device + Addressable> AddressableDevice for T { }
pub struct System {
pub clock: Clock,
pub devices: Vec<RefCell<Box<dyn AddressableDevice>>>,
pub bus: Bus,
}
impl System {
pub fn new() -> System {
System {
clock: 0,
devices: vec![],
bus: Bus::new(),
}
}
pub fn add_device(&mut self, addr: Address, device: Box<dyn AddressableDevice>) -> Result<(), Error> {
self.bus.insert(addr, device.len(), self.devices.len() as DeviceNumber);
self.devices.push(RefCell::new(device));
Ok(())
}
pub fn step(&mut self) -> Result<(), Error> {
self.clock += 1;
for dev in &self.devices {
dev.borrow_mut().step(&self)?;
}
Ok(())
}
pub fn get_device_in_range(&self, addr: Address, count: usize) -> Result<(DeviceRefMut<'_>, Address), Error> {
let (dev, relative_addr) = self.bus.get_device_at(addr, count)?;
Ok((self.devices[dev as usize].borrow_mut(), relative_addr))
}
pub fn read(&self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
let (dev, relative_addr) = self.bus.get_device_at(addr, count)?;
self.devices[dev as usize].borrow_mut().read(relative_addr, count)
}
pub fn write(&self, addr: Address, data: &[u8]) -> Result<(), Error> {
let (dev, relative_addr) = self.bus.get_device_at(addr, data.len())?;
self.devices[dev as usize].borrow_mut().write(relative_addr, data)
}
pub fn read_u8(&self, addr: Address) -> Result<u8, Error> {
Ok(self.read(addr, 1)?[0])
}
pub fn read_beu16(&self, addr: Address) -> Result<u16, Error> {
Ok(memory::read_beu16(&self.read(addr, 2)?))
}
pub fn read_beu32(&self, addr: Address) -> Result<u32, Error> {
Ok(memory::read_beu32(&self.read(addr, 4)?))
}
pub fn write_u8(&self, addr: Address, value: u8) -> Result<(), Error> {
let data = [value];
self.write(addr, &data)
}
pub fn write_beu16(&self, addr: Address, value: u16) -> Result<(), Error> {
let data = memory::write_beu16(value);
self.write(addr, &data)
}
pub fn write_beu32(&self, addr: Address, value: u32) -> Result<(), Error> {
let data = memory::write_beu32(value);
self.write(addr, &data)
}
pub fn dump_memory(&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 _ 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);
}
}
}