mirror of
https://github.com/transistorfet/moa.git
synced 2024-09-11 05:54:44 +00:00
Fixed alloc in harte_tests that was taking all the time
This commit is contained in:
parent
545f339fe2
commit
59306bceff
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -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",
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,4 +13,4 @@ emulator-hal = { path = "../../libraries/emulator-hal/emulator-hal" }
|
||||
moa-core = { path = "../../core", optional = true }
|
||||
|
||||
[features]
|
||||
moa = []
|
||||
moa = ["moa-core"]
|
||||
|
@ -17,7 +17,7 @@ fn main() {
|
||||
for word in words.iter() {
|
||||
print!("{:04x} ", word);
|
||||
}
|
||||
println!("");
|
||||
println!();
|
||||
},
|
||||
Err(err) => {
|
||||
println!("{:?}", err);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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],
|
||||
}
|
||||
}
|
||||
|
@ -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>> {
|
||||
|
@ -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> {
|
||||
|
@ -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!();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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") {
|
||||
|
@ -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")
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user