mirror of
https://github.com/transistorfet/moa.git
synced 2024-06-25 18:29:33 +00:00
Refactored such that System is the top level object
This commit is contained in:
parent
5ea2ccc128
commit
e186637f49
|
@ -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" => {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -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);
|
||||
},
|
||||
}
|
||||
|
|
114
src/memory.rs
114
src/memory.rs
|
@ -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,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
116
src/system.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user