Fixed alloc in harte_tests that was taking all the time
This commit is contained in:
parent
545f339fe2
commit
59306bceff
|
@ -425,6 +425,13 @@ dependencies = [
|
||||||
"fugit",
|
"fugit",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "emulator-hal-memory"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"emulator-hal",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_logger"
|
name = "env_logger"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
@ -510,6 +517,8 @@ name = "harte-tests"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap 3.2.25",
|
"clap 3.2.25",
|
||||||
|
"emulator-hal",
|
||||||
|
"emulator-hal-memory",
|
||||||
"femtos",
|
"femtos",
|
||||||
"flate2",
|
"flate2",
|
||||||
"moa-core",
|
"moa-core",
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::error::{Error as StdError};
|
|
||||||
use moa_host::HostError;
|
use moa_host::HostError;
|
||||||
|
|
||||||
use emulator_hal::bus;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum EmulatorErrorKind {
|
pub enum EmulatorErrorKind {
|
||||||
Misc,
|
Misc,
|
||||||
|
@ -78,7 +75,7 @@ impl fmt::Display for Error {
|
||||||
|
|
||||||
impl<E> From<HostError<E>> for Error {
|
impl<E> From<HostError<E>> for Error {
|
||||||
fn from(err: HostError<E>) -> Self {
|
fn from(err: HostError<E>) -> Self {
|
||||||
Self::Other(format!("other"))
|
Self::Other("other".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,4 @@ emulator-hal = { path = "../../libraries/emulator-hal/emulator-hal" }
|
||||||
moa-core = { path = "../../core", optional = true }
|
moa-core = { path = "../../core", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
moa = []
|
moa = ["moa-core"]
|
||||||
|
|
|
@ -17,7 +17,7 @@ fn main() {
|
||||||
for word in words.iter() {
|
for word in words.iter() {
|
||||||
print!("{:04x} ", word);
|
print!("{:04x} ", word);
|
||||||
}
|
}
|
||||||
println!("");
|
println!();
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("{:?}", err);
|
println!("{:?}", err);
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
|
|
||||||
use femtos::Instant;
|
use femtos::Instant;
|
||||||
use emulator_hal::bus::{self, BusAccess};
|
use emulator_hal::bus::BusAccess;
|
||||||
|
|
||||||
use super::state::{M68k, M68kError};
|
use super::state::M68kError;
|
||||||
use super::decode::M68kDecoder;
|
|
||||||
use super::execute::M68kCycleExecutor;
|
use super::execute::M68kCycleExecutor;
|
||||||
use super::memory::M68kAddress;
|
use super::memory::M68kAddress;
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub struct InstructionDecoding<'a, Bus>
|
||||||
where
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant>,
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
{
|
{
|
||||||
pub(crate) port: &'a mut Bus,
|
pub(crate) bus: &'a mut Bus,
|
||||||
pub(crate) memory: &'a mut M68kBusPort,
|
pub(crate) memory: &'a mut M68kBusPort,
|
||||||
pub(crate) decoder: &'a mut M68kDecoder,
|
pub(crate) decoder: &'a mut M68kDecoder,
|
||||||
}
|
}
|
||||||
|
@ -78,13 +78,13 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant>,
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
{
|
{
|
||||||
self.init(is_supervisor, start);
|
self.init(is_supervisor, start);
|
||||||
let mut decoding = InstructionDecoding {
|
let mut decoding = InstructionDecoding {
|
||||||
port,
|
bus,
|
||||||
memory,
|
memory,
|
||||||
decoder: self,
|
decoder: self,
|
||||||
};
|
};
|
||||||
|
@ -92,22 +92,22 @@ impl M68kDecoder {
|
||||||
Ok(())
|
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
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant>,
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
{
|
{
|
||||||
let mut next = start;
|
let mut next = start;
|
||||||
while next < (start + length) {
|
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(()) => {
|
Ok(()) => {
|
||||||
self.dump_decoded(memory.current_clock, port);
|
self.dump_decoded(memory.current_clock, bus);
|
||||||
next = self.end;
|
next = self.end;
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("{:?}", err);
|
println!("{:?}", err);
|
||||||
match err {
|
match err {
|
||||||
M68kError::Exception(ex) if ex == Exceptions::IllegalInstruction => {
|
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
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant>,
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
{
|
{
|
||||||
let ins_data: Result<String, M68kError<Bus::Error>> =
|
let ins_data: Result<String, M68kError<Bus::Error>> =
|
||||||
(0..((self.end - self.start) / 2)).map(|offset|
|
(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();
|
).collect();
|
||||||
println!("{:#010x}: {}\n\t{}\n", self.start, ins_data.unwrap(), self.instruction);
|
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>> {
|
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;
|
self.decoder.end += 2;
|
||||||
Ok(word)
|
Ok(word)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_instruction_long(&mut self) -> Result<u32, M68kError<Bus::Error>> {
|
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;
|
self.decoder.end += 4;
|
||||||
Ok(word)
|
Ok(word)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
use femtos::Instant;
|
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::state::{M68k, M68kType, M68kError, M68kState, Status, Flags, Exceptions, InterruptPriority};
|
||||||
use crate::memory::{MemType, MemAccess, M68kBusPort, M68kAddress};
|
use crate::memory::{MemType, MemAccess, M68kBusPort, M68kAddress};
|
||||||
|
@ -64,7 +65,7 @@ impl M68kCycle {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant>,
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
{
|
{
|
||||||
|
@ -78,19 +79,52 @@ impl M68kCycle {
|
||||||
|
|
||||||
M68kCycleExecutor {
|
M68kCycleExecutor {
|
||||||
state: &mut cpu.state,
|
state: &mut cpu.state,
|
||||||
port: bus,
|
bus: bus,
|
||||||
debugger: &mut cpu.debugger,
|
debugger: &mut cpu.debugger,
|
||||||
cycle: self,
|
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>
|
pub struct M68kCycleExecutor<'a, Bus>
|
||||||
where
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant>,
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
{
|
{
|
||||||
pub state: &'a mut M68kState,
|
pub state: &'a mut M68kState,
|
||||||
pub port: Bus,
|
pub bus: Bus,
|
||||||
pub debugger: &'a mut M68kDebugger,
|
pub debugger: &'a mut M68kDebugger,
|
||||||
pub cycle: M68kCycle,
|
pub cycle: M68kCycle,
|
||||||
}
|
}
|
||||||
|
@ -298,7 +332,7 @@ where
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn decode_next(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
pub fn decode_next(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let is_supervisor = self.is_supervisor();
|
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);
|
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>> {
|
fn get_address_sized(&mut self, addr: M68kAddress, size: Size) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
let is_supervisor = self.is_supervisor();
|
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>> {
|
fn set_address_sized(&mut self, addr: M68kAddress, value: u32, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let is_supervisor = self.is_supervisor();
|
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>> {
|
fn push_word(&mut self, value: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let is_supervisor = self.is_supervisor();
|
let is_supervisor = self.is_supervisor();
|
||||||
*self.get_stack_pointer_mut() -= 2;
|
*self.get_stack_pointer_mut() -= 2;
|
||||||
let addr = *self.get_stack_pointer_mut();
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_word(&mut self) -> Result<u16, M68kError<Bus::Error>> {
|
fn pop_word(&mut self) -> Result<u16, M68kError<Bus::Error>> {
|
||||||
let is_supervisor = self.is_supervisor();
|
let is_supervisor = self.is_supervisor();
|
||||||
let addr = *self.get_stack_pointer_mut();
|
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;
|
*self.get_stack_pointer_mut() += 2;
|
||||||
Ok(value as u16)
|
Ok(value as u16)
|
||||||
}
|
}
|
||||||
|
@ -1632,14 +1666,14 @@ where
|
||||||
let is_supervisor = self.is_supervisor();
|
let is_supervisor = self.is_supervisor();
|
||||||
*self.get_stack_pointer_mut() -= 4;
|
*self.get_stack_pointer_mut() -= 4;
|
||||||
let addr = *self.get_stack_pointer_mut();
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_long(&mut self) -> Result<u32, M68kError<Bus::Error>> {
|
fn pop_long(&mut self) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
let is_supervisor = self.is_supervisor();
|
let is_supervisor = self.is_supervisor();
|
||||||
let addr = *self.get_stack_pointer_mut();
|
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;
|
*self.get_stack_pointer_mut() += 4;
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
@ -1677,7 +1711,7 @@ where
|
||||||
match base_reg {
|
match base_reg {
|
||||||
BaseRegister::None => 0,
|
BaseRegister::None => 0,
|
||||||
BaseRegister::PC => self.cycle.decoder.start + 2,
|
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],
|
BaseRegister::AReg(reg) => self.state.a_reg[reg as usize],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
{
|
{
|
||||||
self.start_request(is_supervisor, addr as u32, size, MemAccess::Read, MemType::Data, false)?;
|
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
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
{
|
{
|
||||||
self.start_request(is_supervisor, addr as u32, size, MemAccess::Write, MemType::Data, false)?;
|
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
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
{
|
{
|
||||||
self.request.instruction(is_supervisor, addr)?;
|
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
|
where
|
||||||
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
{
|
{
|
||||||
self.request.instruction(is_supervisor, addr)?;
|
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>> {
|
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>> {
|
||||||
|
|
|
@ -94,15 +94,15 @@ impl Debuggable for M68k {
|
||||||
|
|
||||||
fn print_current_step(&mut self, _system: &System) -> Result<(), Error> {
|
fn print_current_step(&mut self, _system: &System) -> Result<(), Error> {
|
||||||
// TODO this is called by the debugger, but should be called some other way
|
// 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);
|
//let _ = self.decoder.decode_at(&mut self.bus, true, self.state.pc);
|
||||||
//self.decoder.dump_decoded(&mut self.port);
|
//self.decoder.dump_decoded(&mut self.bus);
|
||||||
//self.dump_state();
|
//self.dump_state();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_disassembly(&mut self, addr: Address, count: usize) {
|
fn print_disassembly(&mut self, addr: Address, count: usize) {
|
||||||
let mut decoder = M68kDecoder::new(self.info.chip, true, 0);
|
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> {
|
fn run_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {
|
||||||
|
|
|
@ -272,7 +272,7 @@ impl M68k {
|
||||||
println!("Current Instruction: {:#010x} {:?}", cycle.decoder.start, cycle.decoder.instruction);
|
println!("Current Instruction: {:#010x} {:?}", cycle.decoder.start, cycle.decoder.instruction);
|
||||||
println!();
|
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!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ fn main() {
|
||||||
system.add_addressable_device(0x00700000, Device::new(serial)).unwrap();
|
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.enable_tracing();
|
||||||
//cpu.add_breakpoint(0x10781a);
|
//cpu.add_breakpoint(0x10781a);
|
||||||
|
|
|
@ -18,7 +18,7 @@ fn main() {
|
||||||
options.rom = filename.to_string();
|
options.rom = filename.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut frontend = ConsoleFrontend::new();
|
let mut frontend = ConsoleFrontend::default();
|
||||||
|
|
||||||
let system = build_computie(&mut frontend, options).unwrap();
|
let system = build_computie(&mut frontend, options).unwrap();
|
||||||
frontend.start(matches, system);
|
frontend.start(matches, system);
|
||||||
|
|
|
@ -10,7 +10,7 @@ fn main() {
|
||||||
.help("ROM file to load (must be flat binary)"))
|
.help("ROM file to load (must be flat binary)"))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let mut frontend = ConsoleFrontend::new();
|
let mut frontend = ConsoleFrontend::default();
|
||||||
|
|
||||||
let mut options = SegaGenesisOptions::default();
|
let mut options = SegaGenesisOptions::default();
|
||||||
if let Some(filename) = matches.get_one::<String>("ROM") {
|
if let Some(filename) = matches.get_one::<String>("ROM") {
|
||||||
|
|
|
@ -33,11 +33,13 @@ impl Host for ConsoleFrontend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConsoleFrontend {
|
impl Default for ConsoleFrontend {
|
||||||
pub fn new() -> Self {
|
fn default() -> Self {
|
||||||
Self
|
Self
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConsoleFrontend {
|
||||||
pub fn args(application_name: &'static str) -> Command {
|
pub fn args(application_name: &'static str) -> Command {
|
||||||
Command::new(application_name)
|
Command::new(application_name)
|
||||||
.arg(Arg::new("log-level")
|
.arg(Arg::new("log-level")
|
||||||
|
|
|
@ -5,9 +5,13 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
femtos = "0.1"
|
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-core = { path = "../../emulator/core" }
|
||||||
moa-m68k = { path = "../../emulator/cpus/m68k", features = ["moa"] }
|
moa-m68k = { path = "../../emulator/cpus/m68k", features = ["moa"] }
|
||||||
|
|
||||||
|
#thiserror = "1.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
|
|
@ -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
|
ABCD.json.gz completed: 7993 passed, 72 FAILED
|
||||||
ADD.b.json.gz completed, all passed!
|
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!
|
CMPA.w.json.gz completed, all passed!
|
||||||
DBcc.json.gz completed, all passed!
|
DBcc.json.gz completed, all passed!
|
||||||
DIVS.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
|
||||||
|
|
|
@ -10,13 +10,22 @@ use std::fs::{self, File};
|
||||||
use clap::{Parser, ArgEnum};
|
use clap::{Parser, ArgEnum};
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
use serde_derive::Deserialize;
|
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::{M68k, M68kType};
|
||||||
use moa_m68k::state::Status;
|
use moa_m68k::state::Status;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum Error {
|
||||||
|
Assertion(String),
|
||||||
|
Bus(String),
|
||||||
|
Step(String),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ArgEnum)]
|
#[derive(Copy, Clone, PartialEq, Eq, ArgEnum)]
|
||||||
enum Selection {
|
enum Selection {
|
||||||
Include,
|
Include,
|
||||||
|
@ -106,7 +115,7 @@ impl TestState {
|
||||||
for word in self.prefetch.iter() {
|
for word in self.prefetch.iter() {
|
||||||
print!("{:04x} ", *word);
|
print!("{:04x} ", *word);
|
||||||
}
|
}
|
||||||
println!("");
|
println!();
|
||||||
|
|
||||||
println!("ram: ");
|
println!("ram: ");
|
||||||
for (addr, byte) in self.ram.iter() {
|
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> {
|
fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, MemoryBlock<u32, Instant>), Error> {
|
||||||
let mut system = System::default();
|
|
||||||
|
|
||||||
// Insert basic initialization
|
// Insert basic initialization
|
||||||
let data = vec![0; 0x01000000];
|
let len = 0x100_0000;
|
||||||
let mem = MemoryBlock::new(data);
|
let mut data = Vec::with_capacity(len);
|
||||||
system.add_addressable_device(0x00000000, Device::new(mem)).unwrap();
|
unsafe { data.set_len(len); }
|
||||||
|
let mut memory = MemoryBlock::<u32, Instant>::from(data);
|
||||||
|
|
||||||
let port = if cputype <= M68kType::MC68010 {
|
let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10));
|
||||||
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);
|
|
||||||
cpu.state.status = Status::Running;
|
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>
|
fn assert_value<T>(actual: T, expected: T, message: &str) -> Result<(), Error>
|
||||||
|
@ -165,11 +168,11 @@ where
|
||||||
if actual == expected {
|
if actual == expected {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} 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[0] = initial.d0;
|
||||||
cpu.state.d_reg[1] = initial.d1;
|
cpu.state.d_reg[1] = initial.d1;
|
||||||
cpu.state.d_reg[2] = initial.d2;
|
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
|
// Load instructions into memory
|
||||||
for (i, ins) in initial.prefetch.iter().enumerate() {
|
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
|
// Load data bytes into memory
|
||||||
for (addr, byte) in initial.ram.iter() {
|
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(())
|
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[0], expected.d0, "d0")?;
|
||||||
assert_value(cpu.state.d_reg[1], expected.d1, "d1")?;
|
assert_value(cpu.state.d_reg[1], expected.d1, "d1")?;
|
||||||
assert_value(cpu.state.d_reg[2], expected.d2, "d2")?;
|
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.sr, expected.sr, "sr")?;
|
||||||
assert_value(cpu.state.pc, expected.pc, "pc")?;
|
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
|
// Load instructions into memory
|
||||||
for (i, ins) in expected.prefetch.iter().enumerate() {
|
for (i, ins) in expected.prefetch.iter().enumerate() {
|
||||||
let addr = expected.pc + (i as u32 * 2);
|
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))?;
|
assert_value(actual, *ins, &format!("prefetch at {:x}", addr))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load data bytes into memory
|
// Load data bytes into memory
|
||||||
for (addr, byte) in expected.ram.iter() {
|
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))?;
|
assert_value(actual, *byte, &format!("ram at {:x}", addr))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_cpu_and_assert(cpu: &mut M68k, system: &System, case: &TestCase, test_timing: bool) -> Result<(), Error> {
|
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(&system)?;
|
let clock_elapsed = cpu.step(Instant::START, memory)
|
||||||
let cycles = clock_elapsed / cpu.info.frequency.period_duration();
|
.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 {
|
if test_timing {
|
||||||
assert_value(cycles, case.length as u64, "clock cycles")?;
|
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> {
|
fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> {
|
||||||
let (mut cpu, system) = init_execute_test(M68kType::MC68000, &case.initial_state).unwrap();
|
let (mut cpu, mut memory) = init_execute_test(M68kType::MC68000, &case.initial_state).unwrap();
|
||||||
let mut initial_cpu = cpu.clone();
|
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 {
|
match result {
|
||||||
Ok(()) => Ok(()),
|
Ok(()) => Ok(()),
|
||||||
|
@ -268,7 +276,7 @@ fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> {
|
||||||
if !args.quiet {
|
if !args.quiet {
|
||||||
if args.debug {
|
if args.debug {
|
||||||
case.dump();
|
case.dump();
|
||||||
println!("");
|
println!();
|
||||||
//initial_cpu.dump_state();
|
//initial_cpu.dump_state();
|
||||||
//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!("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);
|
println!("completed in {}m {}s", elapsed_secs / 60, elapsed_secs % 60);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue