Fixed alloc in harte_tests that was taking all the time

This commit is contained in:
transistor 2024-03-14 22:35:02 -07:00
parent 545f339fe2
commit 59306bceff
17 changed files with 227 additions and 84 deletions

9
Cargo.lock generated
View File

@ -425,6 +425,13 @@ dependencies = [
"fugit",
]
[[package]]
name = "emulator-hal-memory"
version = "0.1.0"
dependencies = [
"emulator-hal",
]
[[package]]
name = "env_logger"
version = "0.8.4"
@ -510,6 +517,8 @@ name = "harte-tests"
version = "0.1.0"
dependencies = [
"clap 3.2.25",
"emulator-hal",
"emulator-hal-memory",
"femtos",
"flate2",
"moa-core",

View File

@ -1,10 +1,7 @@
use std::fmt;
use std::error::{Error as StdError};
use moa_host::HostError;
use emulator_hal::bus;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum EmulatorErrorKind {
Misc,
@ -78,7 +75,7 @@ impl fmt::Display for Error {
impl<E> From<HostError<E>> for Error {
fn from(err: HostError<E>) -> Self {
Self::Other(format!("other"))
Self::Other("other".to_string())
}
}

View File

@ -13,4 +13,4 @@ emulator-hal = { path = "../../libraries/emulator-hal/emulator-hal" }
moa-core = { path = "../../core", optional = true }
[features]
moa = []
moa = ["moa-core"]

View File

@ -17,7 +17,7 @@ fn main() {
for word in words.iter() {
print!("{:04x} ", word);
}
println!("");
println!();
},
Err(err) => {
println!("{:?}", err);

View File

@ -1,9 +1,8 @@
use femtos::Instant;
use emulator_hal::bus::{self, BusAccess};
use emulator_hal::bus::BusAccess;
use super::state::{M68k, M68kError};
use super::decode::M68kDecoder;
use super::state::M68kError;
use super::execute::M68kCycleExecutor;
use super::memory::M68kAddress;

View File

@ -52,7 +52,7 @@ pub struct InstructionDecoding<'a, Bus>
where
Bus: BusAccess<M68kAddress, Instant>,
{
pub(crate) port: &'a mut Bus,
pub(crate) bus: &'a mut Bus,
pub(crate) memory: &'a mut M68kBusPort,
pub(crate) decoder: &'a mut M68kDecoder,
}
@ -78,13 +78,13 @@ impl M68kDecoder {
}
#[inline]
pub fn decode_at<Bus>(&mut self, port: &mut Bus, memory: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError<Bus::Error>>
pub fn decode_at<Bus>(&mut self, bus: &mut Bus, memory: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError<Bus::Error>>
where
Bus: BusAccess<M68kAddress, Instant>,
{
self.init(is_supervisor, start);
let mut decoding = InstructionDecoding {
port,
bus,
memory,
decoder: self,
};
@ -92,22 +92,22 @@ impl M68kDecoder {
Ok(())
}
pub fn dump_disassembly<Bus>(&mut self, port: &mut Bus, memory: &mut M68kBusPort, start: u32, length: u32)
pub fn dump_disassembly<Bus>(&mut self, bus: &mut Bus, memory: &mut M68kBusPort, start: u32, length: u32)
where
Bus: BusAccess<M68kAddress, Instant>,
{
let mut next = start;
while next < (start + length) {
match self.decode_at(port, memory, self.is_supervisor, next) {
match self.decode_at(bus, memory, self.is_supervisor, next) {
Ok(()) => {
self.dump_decoded(memory.current_clock, port);
self.dump_decoded(memory.current_clock, bus);
next = self.end;
},
Err(err) => {
println!("{:?}", err);
match err {
M68kError::Exception(ex) if ex == Exceptions::IllegalInstruction => {
println!(" at {:08x}: {:04x}", self.start, port.read_beu16(memory.current_clock, self.start).unwrap());
println!(" at {:08x}: {:04x}", self.start, bus.read_beu16(memory.current_clock, self.start).unwrap());
},
_ => { },
}
@ -117,13 +117,13 @@ impl M68kDecoder {
}
}
pub fn dump_decoded<Bus>(&mut self, clock: Instant, port: &mut Bus)
pub fn dump_decoded<Bus>(&mut self, clock: Instant, bus: &mut Bus)
where
Bus: BusAccess<M68kAddress, Instant>,
{
let ins_data: Result<String, M68kError<Bus::Error>> =
(0..((self.end - self.start) / 2)).map(|offset|
Ok(format!("{:04x} ", port.read_beu16(clock, self.start + (offset * 2)).unwrap()))
Ok(format!("{:04x} ", bus.read_beu16(clock, self.start + (offset * 2)).unwrap()))
).collect();
println!("{:#010x}: {}\n\t{}\n", self.start, ins_data.unwrap(), self.instruction);
}
@ -731,13 +731,13 @@ where
}
fn read_instruction_word(&mut self) -> Result<u16, M68kError<Bus::Error>> {
let word = self.memory.read_instruction_word(self.port, self.decoder.is_supervisor, self.decoder.end)?;
let word = self.memory.read_instruction_word(self.bus, self.decoder.is_supervisor, self.decoder.end)?;
self.decoder.end += 2;
Ok(word)
}
fn read_instruction_long(&mut self) -> Result<u32, M68kError<Bus::Error>> {
let word = self.memory.read_instruction_long(self.port, self.decoder.is_supervisor, self.decoder.end)?;
let word = self.memory.read_instruction_long(self.bus, self.decoder.is_supervisor, self.decoder.end)?;
self.decoder.end += 4;
Ok(word)
}

View File

@ -1,6 +1,7 @@
use femtos::Instant;
use emulator_hal::bus::BusAccess;
use emulator_hal::bus::{self, BusAccess};
use emulator_hal::step::Step;
use crate::state::{M68k, M68kType, M68kError, M68kState, Status, Flags, Exceptions, InterruptPriority};
use crate::memory::{MemType, MemAccess, M68kBusPort, M68kAddress};
@ -64,7 +65,7 @@ impl M68kCycle {
}
#[inline]
pub fn begin<'a, Bus>(mut self, cpu: &'a mut M68k, bus: Bus) -> M68kCycleExecutor<'a, Bus>
pub fn begin<Bus>(self, cpu: &mut M68k, bus: Bus) -> M68kCycleExecutor<'_, Bus>
where
Bus: BusAccess<M68kAddress, Instant>,
{
@ -78,19 +79,52 @@ impl M68kCycle {
M68kCycleExecutor {
state: &mut cpu.state,
port: bus,
bus: bus,
debugger: &mut cpu.debugger,
cycle: self,
}
}
}
impl<Bus, BusError> Step<M68kAddress, Instant, Bus> for M68k
where
BusError: bus::Error,
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
{
type Error = M68kError<BusError>;
fn is_running(&mut self) -> bool {
self.state.status == Status::Running
}
fn reset(&mut self, now: Instant, bus: &mut Bus) -> Result<(), Self::Error> {
Ok(())
}
fn step(&mut self, now: Instant, bus: &mut Bus) -> Result<Instant, Self::Error> {
let cycle = M68kCycle::new(self, now);
let mut executor = cycle.begin(self, &mut *bus);
executor.check_breakpoints()?;
executor.step()?;
//let interrupt = system.get_interrupt_controller().check();
//if let (priority, Some(ack)) = executor.check_pending_interrupts(interrupt)? {
// log::debug!("interrupt: {:?} @ {} ns", priority, system.clock.as_duration().as_nanos());
// system.get_interrupt_controller().acknowledge(priority as u8)?;
//}
self.cycle = Some(executor.end());
Ok(now + self.last_cycle_duration())
}
}
pub struct M68kCycleExecutor<'a, Bus>
where
Bus: BusAccess<M68kAddress, Instant>,
{
pub state: &'a mut M68kState,
pub port: Bus,
pub bus: Bus,
pub debugger: &'a mut M68kDebugger,
pub cycle: M68kCycle,
}
@ -298,7 +332,7 @@ where
#[inline]
pub fn decode_next(&mut self) -> Result<(), M68kError<Bus::Error>> {
let is_supervisor = self.is_supervisor();
self.cycle.decoder.decode_at(&mut self.port, &mut self.cycle.memory, is_supervisor, self.state.pc)?;
self.cycle.decoder.decode_at(&mut self.bus, &mut self.cycle.memory, is_supervisor, self.state.pc)?;
self.cycle.timing.add_instruction(&self.cycle.decoder.instruction);
@ -1604,26 +1638,26 @@ where
fn get_address_sized(&mut self, addr: M68kAddress, size: Size) -> Result<u32, M68kError<Bus::Error>> {
let is_supervisor = self.is_supervisor();
self.cycle.memory.read_data_sized(&mut self.port, is_supervisor, addr, size)
self.cycle.memory.read_data_sized(&mut self.bus, is_supervisor, addr, size)
}
fn set_address_sized(&mut self, addr: M68kAddress, value: u32, size: Size) -> Result<(), M68kError<Bus::Error>> {
let is_supervisor = self.is_supervisor();
self.cycle.memory.write_data_sized(&mut self.port, is_supervisor, addr, size, value)
self.cycle.memory.write_data_sized(&mut self.bus, is_supervisor, addr, size, value)
}
fn push_word(&mut self, value: u16) -> Result<(), M68kError<Bus::Error>> {
let is_supervisor = self.is_supervisor();
*self.get_stack_pointer_mut() -= 2;
let addr = *self.get_stack_pointer_mut();
self.cycle.memory.write_data_sized(&mut self.port, is_supervisor, addr, Size::Word, value as u32)?;
self.cycle.memory.write_data_sized(&mut self.bus, is_supervisor, addr, Size::Word, value as u32)?;
Ok(())
}
fn pop_word(&mut self) -> Result<u16, M68kError<Bus::Error>> {
let is_supervisor = self.is_supervisor();
let addr = *self.get_stack_pointer_mut();
let value = self.cycle.memory.read_data_sized(&mut self.port, is_supervisor, addr, Size::Word)?;
let value = self.cycle.memory.read_data_sized(&mut self.bus, is_supervisor, addr, Size::Word)?;
*self.get_stack_pointer_mut() += 2;
Ok(value as u16)
}
@ -1632,14 +1666,14 @@ where
let is_supervisor = self.is_supervisor();
*self.get_stack_pointer_mut() -= 4;
let addr = *self.get_stack_pointer_mut();
self.cycle.memory.write_data_sized(&mut self.port, is_supervisor, addr, Size::Long, value)?;
self.cycle.memory.write_data_sized(&mut self.bus, is_supervisor, addr, Size::Long, value)?;
Ok(())
}
fn pop_long(&mut self) -> Result<u32, M68kError<Bus::Error>> {
let is_supervisor = self.is_supervisor();
let addr = *self.get_stack_pointer_mut();
let value = self.cycle.memory.read_data_sized(&mut self.port, is_supervisor, addr, Size::Long)?;
let value = self.cycle.memory.read_data_sized(&mut self.bus, is_supervisor, addr, Size::Long)?;
*self.get_stack_pointer_mut() += 4;
Ok(value)
}
@ -1677,7 +1711,7 @@ where
match base_reg {
BaseRegister::None => 0,
BaseRegister::PC => self.cycle.decoder.start + 2,
BaseRegister::AReg(reg) if reg == 7 => if self.is_supervisor() { self.state.ssp } else { self.state.usp },
BaseRegister::AReg(7) => if self.is_supervisor() { self.state.ssp } else { self.state.usp },
BaseRegister::AReg(reg) => self.state.a_reg[reg as usize],
}
}

View File

@ -200,36 +200,36 @@ impl M68kBusPort {
}
}
pub(crate) fn read_data_sized<Bus, BusError>(&mut self, port: &mut Bus, is_supervisor: bool, addr: M68kAddress, size: Size) -> Result<u32, M68kError<BusError>>
pub(crate) fn read_data_sized<Bus, BusError>(&mut self, bus: &mut Bus, is_supervisor: bool, addr: M68kAddress, size: Size) -> Result<u32, M68kError<BusError>>
where
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
{
self.start_request(is_supervisor, addr as u32, size, MemAccess::Read, MemType::Data, false)?;
self.read_sized(port, addr, size)
self.read_sized(bus, addr, size)
}
pub(crate) fn write_data_sized<Bus, BusError>(&mut self, port: &mut Bus, is_supervisor: bool, addr: M68kAddress, size: Size, value: u32) -> Result<(), M68kError<BusError>>
pub(crate) fn write_data_sized<Bus, BusError>(&mut self, bus: &mut Bus, is_supervisor: bool, addr: M68kAddress, size: Size, value: u32) -> Result<(), M68kError<BusError>>
where
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
{
self.start_request(is_supervisor, addr as u32, size, MemAccess::Write, MemType::Data, false)?;
self.write_sized(port, addr, size, value)
self.write_sized(bus, addr, size, value)
}
pub(crate) fn read_instruction_word<Bus, BusError>(&mut self, port: &mut Bus, is_supervisor: bool, addr: u32) -> Result<u16, M68kError<BusError>>
pub(crate) fn read_instruction_word<Bus, BusError>(&mut self, bus: &mut Bus, is_supervisor: bool, addr: u32) -> Result<u16, M68kError<BusError>>
where
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
{
self.request.instruction(is_supervisor, addr)?;
Ok(self.read_sized(port, addr, Size::Word)? as u16)
Ok(self.read_sized(bus, addr, Size::Word)? as u16)
}
pub(crate) fn read_instruction_long<Bus, BusError>(&mut self, port: &mut Bus, is_supervisor: bool, addr: u32) -> Result<u32, M68kError<BusError>>
pub(crate) fn read_instruction_long<Bus, BusError>(&mut self, bus: &mut Bus, is_supervisor: bool, addr: u32) -> Result<u32, M68kError<BusError>>
where
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
{
self.request.instruction(is_supervisor, addr)?;
self.read_sized(port, addr, Size::Long)
self.read_sized(bus, addr, Size::Long)
}
pub(crate) fn start_request<BusError>(&mut self, is_supervisor: bool, addr: u32, size: Size, access: MemAccess, mtype: MemType, i_n_bit: bool) -> Result<u32, M68kError<BusError>> {

View File

@ -94,15 +94,15 @@ impl Debuggable for M68k {
fn print_current_step(&mut self, _system: &System) -> Result<(), Error> {
// TODO this is called by the debugger, but should be called some other way
//let _ = self.decoder.decode_at(&mut self.port, true, self.state.pc);
//self.decoder.dump_decoded(&mut self.port);
//let _ = self.decoder.decode_at(&mut self.bus, true, self.state.pc);
//self.decoder.dump_decoded(&mut self.bus);
//self.dump_state();
Ok(())
}
fn print_disassembly(&mut self, addr: Address, count: usize) {
let mut decoder = M68kDecoder::new(self.info.chip, true, 0);
//decoder.dump_disassembly(&mut self.port, self.cycle.memory, addr as u32, count as u32);
//decoder.dump_disassembly(&mut self.bus, self.cycle.memory, addr as u32, count as u32);
}
fn run_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {

View File

@ -272,7 +272,7 @@ impl M68k {
println!("Current Instruction: {:#010x} {:?}", cycle.decoder.start, cycle.decoder.instruction);
println!();
}
//memory::dump_memory(&mut self.port, self.cycle.current_clock, self.state.ssp, 0x40);
//memory::dump_memory(&mut self.bus, self.cycle.current_clock, self.state.ssp, 0x40);
println!();
}

View File

@ -28,7 +28,7 @@ fn main() {
system.add_addressable_device(0x00700000, Device::new(serial)).unwrap();
let cpu = M68k::from_type(M68kType::MC68010, Frequency::from_mhz(8), system.bus.clone(), 0);
let cpu = M68k::from_type(M68kType::MC68010, Frequency::from_mhz(8));
//cpu.enable_tracing();
//cpu.add_breakpoint(0x10781a);

View File

@ -18,7 +18,7 @@ fn main() {
options.rom = filename.to_string();
}
let mut frontend = ConsoleFrontend::new();
let mut frontend = ConsoleFrontend::default();
let system = build_computie(&mut frontend, options).unwrap();
frontend.start(matches, system);

View File

@ -10,7 +10,7 @@ fn main() {
.help("ROM file to load (must be flat binary)"))
.get_matches();
let mut frontend = ConsoleFrontend::new();
let mut frontend = ConsoleFrontend::default();
let mut options = SegaGenesisOptions::default();
if let Some(filename) = matches.get_one::<String>("ROM") {

View File

@ -33,11 +33,13 @@ impl Host for ConsoleFrontend {
}
}
impl ConsoleFrontend {
pub fn new() -> Self {
impl Default for ConsoleFrontend {
fn default() -> Self {
Self
}
}
impl ConsoleFrontend {
pub fn args(application_name: &'static str) -> Command {
Command::new(application_name)
.arg(Arg::new("log-level")

View File

@ -5,9 +5,13 @@ edition = "2021"
[dependencies]
femtos = "0.1"
emulator-hal = { path = "../../emulator/libraries/emulator-hal/emulator-hal" }
emulator-hal-memory = { path = "../../emulator/libraries/emulator-hal/emulator-hal-memory" }
moa-core = { path = "../../emulator/core" }
moa-m68k = { path = "../../emulator/cpus/m68k", features = ["moa"] }
#thiserror = "1.0"
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"

View File

@ -1,4 +1,4 @@
Last run on 2024-03-13 at commit af1c660dc0682a62c123b1d7577f2ce2b5f3d8ad
Last run on 2024-03-14 at commit 545f339fe2714cc648bd4a01506518a13c1faf39
ABCD.json.gz completed: 7993 passed, 72 FAILED
ADD.b.json.gz completed, all passed!
@ -37,3 +37,93 @@ CMPA.l.json.gz completed, all passed!
CMPA.w.json.gz completed, all passed!
DBcc.json.gz completed, all passed!
DIVS.json.gz completed, all passed!
DIVU.json.gz completed: 8064 passed, 1 FAILED
EOR.b.json.gz completed, all passed!
EOR.l.json.gz completed: 7519 passed, 546 FAILED
EOR.w.json.gz completed: 7525 passed, 540 FAILED
EORItoCCR.json.gz completed, all passed!
EORItoSR.json.gz completed, all passed!
EXG.json.gz completed, all passed!
EXT.l.json.gz completed, all passed!
EXT.w.json.gz completed, all passed!
JMP.json.gz completed, all passed!
JSR.json.gz completed, all passed!
LEA.json.gz completed, all passed!
LINK.json.gz completed, all passed!
LSL.b.json.gz completed, all passed!
LSL.l.json.gz completed, all passed!
LSL.w.json.gz completed: 7910 passed, 155 FAILED
LSR.b.json.gz completed, all passed!
LSR.l.json.gz completed, all passed!
LSR.w.json.gz completed: 7909 passed, 156 FAILED
MOVE.b.json.gz completed, all passed!
MOVE.l.json.gz completed: 5827 passed, 2238 FAILED
MOVE.q.json.gz completed, all passed!
MOVE.w.json.gz completed: 5855 passed, 2210 FAILED
MOVEA.l.json.gz completed, all passed!
MOVEA.w.json.gz completed, all passed!
MOVEM.l.json.gz completed: 6035 passed, 2030 FAILED
MOVEM.w.json.gz completed: 6431 passed, 1634 FAILED
MOVEP.l.json.gz completed: 4036 passed, 4029 FAILED
MOVEP.w.json.gz completed: 4046 passed, 4019 FAILED
MOVEfromSR.json.gz completed: 6896 passed, 1169 FAILED
MOVEfromUSP.json.gz completed, all passed!
MOVEtoCCR.json.gz completed, all passed!
MOVEtoSR.json.gz completed, all passed!
MOVEtoUSP.json.gz completed, all passed!
MULS.json.gz completed, all passed!
MULU.json.gz completed, all passed!
NBCD.json.gz completed: 8037 passed, 28 FAILED
NEG.b.json.gz completed, all passed!
NEG.l.json.gz completed: 7552 passed, 513 FAILED
NEG.w.json.gz completed: 7531 passed, 534 FAILED
NEGX.b.json.gz completed, all passed!
NEGX.l.json.gz completed: 7520 passed, 545 FAILED
NEGX.w.json.gz completed: 7510 passed, 555 FAILED
NOP.json.gz completed, all passed!
NOT.b.json.gz completed, all passed!
NOT.l.json.gz completed: 7512 passed, 553 FAILED
NOT.w.json.gz completed: 7530 passed, 535 FAILED
OR.b.json.gz completed, all passed!
OR.l.json.gz completed: 7756 passed, 309 FAILED
OR.w.json.gz completed: 7765 passed, 300 FAILED
ORItoCCR.json.gz completed, all passed!
ORItoSR.json.gz completed, all passed!
PEA.json.gz completed, all passed!
RESET.json.gz completed, all passed!
ROL.b.json.gz completed, all passed!
ROL.l.json.gz completed, all passed!
ROL.w.json.gz completed: 7898 passed, 167 FAILED
ROR.b.json.gz completed, all passed!
ROR.l.json.gz completed, all passed!
ROR.w.json.gz completed: 7932 passed, 133 FAILED
ROXL.b.json.gz completed: 8032 passed, 33 FAILED
ROXL.l.json.gz completed: 8029 passed, 36 FAILED
ROXL.w.json.gz completed: 7890 passed, 175 FAILED
ROXR.b.json.gz completed: 8027 passed, 38 FAILED
ROXR.l.json.gz completed: 8039 passed, 26 FAILED
ROXR.w.json.gz completed: 7880 passed, 185 FAILED
RTE.json.gz completed, all passed!
RTR.json.gz completed, all passed!
RTS.json.gz completed, all passed!
SBCD.json.gz completed: 6809 passed, 1256 FAILED
SUB.b.json.gz completed, all passed!
SUB.l.json.gz completed: 7747 passed, 318 FAILED
SUB.w.json.gz completed: 7716 passed, 349 FAILED
SUBA.l.json.gz completed, all passed!
SUBA.w.json.gz completed, all passed!
SUBX.b.json.gz completed, all passed!
SUBX.l.json.gz completed: 5481 passed, 2584 FAILED
SUBX.w.json.gz completed, all passed!
SWAP.json.gz completed, all passed!
Scc.json.gz completed, all passed!
TAS.json.gz completed, all passed!
TRAP.json.gz completed, all passed!
TRAPV.json.gz completed, all passed!
TST.b.json.gz completed, all passed!
TST.l.json.gz completed, all passed!
TST.w.json.gz completed, all passed!
UNLINK.json.gz completed, all passed!
passed: 966037, failed: 34023, total 97%
completed in 15m 0s

View File

@ -10,13 +10,22 @@ use std::fs::{self, File};
use clap::{Parser, ArgEnum};
use flate2::read::GzDecoder;
use serde_derive::Deserialize;
use femtos::Frequency;
use femtos::{Instant, Frequency};
use moa_core::{System, Error, MemoryBlock, BusPort, Address, Addressable, Steppable, Device};
use emulator_hal::bus::BusAccess;
use emulator_hal::step::Step;
use emulator_hal_memory::MemoryBlock;
use moa_m68k::{M68k, M68kType};
use moa_m68k::state::Status;
#[derive(Clone, Debug)]
enum Error {
Assertion(String),
Bus(String),
Step(String),
}
#[derive(Copy, Clone, PartialEq, Eq, ArgEnum)]
enum Selection {
Include,
@ -106,7 +115,7 @@ impl TestState {
for word in self.prefetch.iter() {
print!("{:04x} ", *word);
}
println!("");
println!();
println!("ram: ");
for (addr, byte) in self.ram.iter() {
@ -137,25 +146,19 @@ impl TestCase {
}
fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, System), Error> {
let mut system = System::default();
fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, MemoryBlock<u32, Instant>), Error> {
// Insert basic initialization
let data = vec![0; 0x01000000];
let mem = MemoryBlock::new(data);
system.add_addressable_device(0x00000000, Device::new(mem)).unwrap();
let len = 0x100_0000;
let mut data = Vec::with_capacity(len);
unsafe { data.set_len(len); }
let mut memory = MemoryBlock::<u32, Instant>::from(data);
let port = if cputype <= M68kType::MC68010 {
BusPort::new(0, 24, 16, system.bus.clone())
} else {
BusPort::new(0, 32, 32, system.bus.clone())
};
let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10), system.bus.clone(), 0);
let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10));
cpu.state.status = Status::Running;
load_state(&mut cpu, &mut system, state)?;
load_state(&mut cpu, &mut memory, state)?;
Ok((cpu, system))
Ok((cpu, memory))
}
fn assert_value<T>(actual: T, expected: T, message: &str) -> Result<(), Error>
@ -165,11 +168,11 @@ where
if actual == expected {
Ok(())
} else {
Err(Error::assertion(&format!("{:#X} != {:#X}, {}", actual, expected, message)))
Err(Error::Assertion(format!("{:#X} != {:#X}, {}", actual, expected, message)))
}
}
fn load_state(cpu: &mut M68k, system: &mut System, initial: &TestState) -> Result<(), Error> {
fn load_state(cpu: &mut M68k, memory: &mut MemoryBlock<u32, Instant>, initial: &TestState) -> Result<(), Error> {
cpu.state.d_reg[0] = initial.d0;
cpu.state.d_reg[1] = initial.d1;
cpu.state.d_reg[2] = initial.d2;
@ -193,18 +196,20 @@ fn load_state(cpu: &mut M68k, system: &mut System, initial: &TestState) -> Resul
// Load instructions into memory
for (i, ins) in initial.prefetch.iter().enumerate() {
system.get_bus().write_beu16(system.clock, (initial.pc + (i as u32 * 2)) as u64, *ins)?;
memory.write_beu16(Instant::START, initial.pc + (i as u32 * 2), *ins)
.map_err(|err| Error::Bus(format!("{:?}", err)))?;
}
// Load data bytes into memory
for (addr, byte) in initial.ram.iter() {
system.get_bus().write_u8(system.clock, *addr as u64, *byte)?;
memory.write_u8(Instant::START, *addr, *byte)
.map_err(|err| Error::Bus(format!("{:?}", err)))?;
}
Ok(())
}
fn assert_state(cpu: &M68k, system: &System, expected: &TestState) -> Result<(), Error> {
fn assert_state(cpu: &M68k, memory: &mut MemoryBlock<u32, Instant>, expected: &TestState) -> Result<(), Error> {
assert_value(cpu.state.d_reg[0], expected.d0, "d0")?;
assert_value(cpu.state.d_reg[1], expected.d1, "d1")?;
assert_value(cpu.state.d_reg[2], expected.d2, "d2")?;
@ -226,29 +231,32 @@ fn assert_state(cpu: &M68k, system: &System, expected: &TestState) -> Result<(),
assert_value(cpu.state.sr, expected.sr, "sr")?;
assert_value(cpu.state.pc, expected.pc, "pc")?;
let addr_mask = cpu.port.address_mask();
let addr_mask = 1_u32.wrapping_shl(cpu.info.address_width as u32).wrapping_sub(1);
// Load instructions into memory
for (i, ins) in expected.prefetch.iter().enumerate() {
let addr = expected.pc + (i as u32 * 2);
let actual = system.get_bus().read_beu16(system.clock, addr as Address & addr_mask)?;
let actual = memory.read_beu16(Instant::START, addr & addr_mask)
.map_err(|err| Error::Bus(format!("{:?}", err)))?;
assert_value(actual, *ins, &format!("prefetch at {:x}", addr))?;
}
// Load data bytes into memory
for (addr, byte) in expected.ram.iter() {
let actual = system.get_bus().read_u8(system.clock, *addr as Address & addr_mask)?;
let actual = memory.read_u8(Instant::START, *addr & addr_mask)
.map_err(|err| Error::Bus(format!("{:?}", err)))?;
assert_value(actual, *byte, &format!("ram at {:x}", addr))?;
}
Ok(())
}
fn step_cpu_and_assert(cpu: &mut M68k, system: &System, case: &TestCase, test_timing: bool) -> Result<(), Error> {
let clock_elapsed = cpu.step(&system)?;
let cycles = clock_elapsed / cpu.info.frequency.period_duration();
fn step_cpu_and_assert(cpu: &mut M68k, memory: &mut MemoryBlock<u32, Instant>, case: &TestCase, test_timing: bool) -> Result<(), Error> {
let clock_elapsed = cpu.step(Instant::START, memory)
.map_err(|err| Error::Step(format!("{:?}", err)))?;
let cycles = clock_elapsed.as_duration() / cpu.info.frequency.period_duration();
assert_state(&cpu, &system, &case.final_state)?;
assert_state(cpu, memory, &case.final_state)?;
if test_timing {
assert_value(cycles, case.length as u64, "clock cycles")?;
@ -257,10 +265,10 @@ fn step_cpu_and_assert(cpu: &mut M68k, system: &System, case: &TestCase, test_ti
}
fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> {
let (mut cpu, system) = init_execute_test(M68kType::MC68000, &case.initial_state).unwrap();
let mut initial_cpu = cpu.clone();
let (mut cpu, mut memory) = init_execute_test(M68kType::MC68000, &case.initial_state).unwrap();
let initial_cpu = cpu.clone();
let result = step_cpu_and_assert(&mut cpu, &system, case, args.timing);
let result = step_cpu_and_assert(&mut cpu, &mut memory, case, args.timing);
match result {
Ok(()) => Ok(()),
@ -268,7 +276,7 @@ fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> {
if !args.quiet {
if args.debug {
case.dump();
println!("");
println!();
//initial_cpu.dump_state();
//cpu.dump_state();
}
@ -391,7 +399,7 @@ fn run_all_tests(args: &Args) {
}
}
println!("");
println!();
println!("passed: {}, failed: {}, total {:.0}%", passed, failed, ((passed as f32) / (passed as f32 + failed as f32)) * 100.0);
println!("completed in {}m {}s", elapsed_secs / 60, elapsed_secs % 60);
}