Implemented Inspect and Debug traits from emulator-hal
This commit is contained in:
parent
5cd1111fc7
commit
c74ea8f462
|
@ -1,9 +1,12 @@
|
|||
use femtos::Instant;
|
||||
use emulator_hal::bus::BusAccess;
|
||||
// m68k Debugger
|
||||
|
||||
use super::state::M68kError;
|
||||
use super::execute::M68kCycleExecutor;
|
||||
use super::memory::M68kAddress;
|
||||
use core::fmt;
|
||||
|
||||
use emulator_hal::time;
|
||||
use emulator_hal::bus::{self, BusAccess};
|
||||
use emulator_hal::step::{Inspect, Debug};
|
||||
|
||||
use crate::{M68k, M68kError, M68kAddress, M68kCycleExecutor};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct StackTracer {
|
||||
|
@ -20,6 +23,74 @@ impl StackTracer {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum M68kInfo {
|
||||
State,
|
||||
}
|
||||
|
||||
impl<Bus, BusError, Instant, Writer> Inspect<M68kAddress, Instant, Bus, Writer> for M68k<Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||
BusError: bus::Error,
|
||||
Writer: fmt::Write,
|
||||
{
|
||||
type InfoType = M68kInfo;
|
||||
|
||||
type Error = M68kError<BusError>;
|
||||
|
||||
fn inspect(&mut self, info: Self::InfoType, bus: &mut Bus, writer: &mut Writer) -> Result<(), Self::Error> {
|
||||
match info {
|
||||
M68kInfo::State => self
|
||||
.state
|
||||
.dump_state(writer)
|
||||
.map_err(|_| M68kError::Other("error while formatting state".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn brief_summary(&mut self, bus: &mut Bus, writer: &mut Writer) -> Result<(), Self::Error> {
|
||||
self.inspect(M68kInfo::State, bus, writer)
|
||||
}
|
||||
|
||||
fn detailed_summary(&mut self, bus: &mut Bus, writer: &mut Writer) -> Result<(), Self::Error> {
|
||||
self.inspect(M68kInfo::State, bus, writer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Control the execution of a CPU device for debugging purposes
|
||||
impl<Bus, BusError, Instant, Writer> Debug<M68kAddress, Instant, Bus, Writer> for M68k<Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||
BusError: bus::Error,
|
||||
Instant: time::Instant,
|
||||
Writer: fmt::Write,
|
||||
{
|
||||
// TODO this should be a new type
|
||||
type DebugError = M68kError<BusError>;
|
||||
|
||||
fn get_execution_address(&mut self) -> Result<M68kAddress, Self::DebugError> {
|
||||
Ok(self.state.pc)
|
||||
}
|
||||
|
||||
fn set_execution_address(&mut self, address: M68kAddress) -> Result<(), Self::DebugError> {
|
||||
self.state.pc = address;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_breakpoint(&mut self, address: M68kAddress) {
|
||||
self.debugger.breakpoints.push(address as u32);
|
||||
}
|
||||
|
||||
fn remove_breakpoint(&mut self, address: M68kAddress) {
|
||||
if let Some(index) = self.debugger.breakpoints.iter().position(|a| *a == address as u32) {
|
||||
self.debugger.breakpoints.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_breakpoints(&mut self) {
|
||||
self.debugger.breakpoints.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct M68kDebugger {
|
||||
|
@ -30,9 +101,10 @@ pub struct M68kDebugger {
|
|||
pub(crate) stack_tracer: StackTracer,
|
||||
}
|
||||
|
||||
impl<'a, Bus, BusError> M68kCycleExecutor<'a, Bus>
|
||||
impl<'a, Bus, BusError, Instant> M68kCycleExecutor<'a, Bus, Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||
Instant: Copy,
|
||||
{
|
||||
pub fn check_breakpoints(&mut self) -> Result<(), M68kError<BusError>> {
|
||||
for breakpoint in &self.debugger.breakpoints {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use femtos::Instant;
|
||||
// Instruction Decoding
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use emulator_hal::bus::BusAccess;
|
||||
|
||||
use crate::state::{M68kType, M68kError, Exceptions};
|
||||
use crate::memory::{M68kBusPort, M68kAddress};
|
||||
use crate::{M68kType, M68kError, M68kBusPort, M68kAddress, Exceptions};
|
||||
use crate::instructions::{
|
||||
Size, Sign, Direction, XRegister, BaseRegister, IndexRegister, RegOrImmediate, ControlRegister, Condition, Target, Instruction,
|
||||
sign_extend_to_long,
|
||||
|
@ -28,27 +29,31 @@ const OPCG_FLINE: u8 = 0xF;
|
|||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct M68kDecoder {
|
||||
pub struct M68kDecoder<Instant> {
|
||||
pub cputype: M68kType,
|
||||
pub is_supervisor: bool,
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
pub instruction_word: u16,
|
||||
pub instruction: Instruction,
|
||||
pub instant: PhantomData<Instant>,
|
||||
}
|
||||
|
||||
pub struct InstructionDecoding<'a, Bus>
|
||||
pub struct InstructionDecoding<'a, Bus, Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant>,
|
||||
{
|
||||
pub(crate) bus: &'a mut Bus,
|
||||
pub(crate) memory: &'a mut M68kBusPort,
|
||||
pub(crate) decoder: &'a mut M68kDecoder,
|
||||
pub(crate) memory: &'a mut M68kBusPort<Instant>,
|
||||
pub(crate) decoder: &'a mut M68kDecoder<Instant>,
|
||||
}
|
||||
|
||||
impl M68kDecoder {
|
||||
impl<Instant> M68kDecoder<Instant>
|
||||
where
|
||||
Instant: Copy,
|
||||
{
|
||||
#[inline]
|
||||
pub fn new(cputype: M68kType, is_supervisor: bool, start: u32) -> M68kDecoder {
|
||||
pub fn new(cputype: M68kType, is_supervisor: bool, start: u32) -> M68kDecoder<Instant> {
|
||||
M68kDecoder {
|
||||
cputype,
|
||||
is_supervisor,
|
||||
|
@ -56,6 +61,7 @@ impl M68kDecoder {
|
|||
end: start,
|
||||
instruction_word: 0,
|
||||
instruction: Instruction::NOP,
|
||||
instant: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +76,7 @@ impl M68kDecoder {
|
|||
pub fn decode_at<Bus>(
|
||||
&mut self,
|
||||
bus: &mut Bus,
|
||||
memory: &mut M68kBusPort,
|
||||
memory: &mut M68kBusPort<Instant>,
|
||||
is_supervisor: bool,
|
||||
start: u32,
|
||||
) -> Result<(), M68kError<Bus::Error>>
|
||||
|
@ -87,14 +93,13 @@ impl M68kDecoder {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn dump_disassembly<Bus>(&mut self, bus: &mut Bus, start: u32, length: u32)
|
||||
pub fn dump_disassembly<Bus>(&mut self, bus: &mut Bus, memory: &mut M68kBusPort<Instant>, start: u32, length: u32)
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant>,
|
||||
{
|
||||
let mut memory = M68kBusPort::default();
|
||||
let mut next = start;
|
||||
while next < (start + length) {
|
||||
match self.decode_at(bus, &mut memory, self.is_supervisor, next) {
|
||||
match self.decode_at(bus, memory, self.is_supervisor, next) {
|
||||
Ok(()) => {
|
||||
self.dump_decoded(memory.current_clock, bus);
|
||||
next = self.end;
|
||||
|
@ -121,9 +126,10 @@ impl M68kDecoder {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Bus> InstructionDecoding<'a, Bus>
|
||||
impl<'a, Bus, Instant> InstructionDecoding<'a, Bus, Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant>,
|
||||
Instant: Copy,
|
||||
{
|
||||
#[inline]
|
||||
pub fn decode_next(&mut self) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use femtos::Instant;
|
||||
use emulator_hal::bus::{self, BusAccess};
|
||||
use emulator_hal::step::Step;
|
||||
// Instruction Execution
|
||||
|
||||
use crate::state::{M68k, M68kType, M68kError, M68kState, Status, Flags, Exceptions, InterruptPriority};
|
||||
use emulator_hal::time;
|
||||
use emulator_hal::step::Step;
|
||||
use emulator_hal::bus::{self, BusAccess};
|
||||
|
||||
use crate::{M68k, M68kType, M68kError, M68kState};
|
||||
use crate::state::{Status, Flags, Exceptions, InterruptPriority};
|
||||
use crate::memory::{MemType, MemAccess, M68kBusPort, M68kAddress};
|
||||
use crate::decode::M68kDecoder;
|
||||
use crate::debugger::M68kDebugger;
|
||||
|
@ -23,14 +26,17 @@ pub enum Used {
|
|||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct M68kCycle {
|
||||
pub decoder: M68kDecoder,
|
||||
pub struct M68kCycle<Instant> {
|
||||
pub decoder: M68kDecoder<Instant>,
|
||||
pub timing: M68kInstructionTiming,
|
||||
pub memory: M68kBusPort,
|
||||
pub memory: M68kBusPort<Instant>,
|
||||
pub current_clock: Instant,
|
||||
}
|
||||
|
||||
impl M68kCycle {
|
||||
impl<Instant> M68kCycle<Instant>
|
||||
where
|
||||
Instant: time::Instant,
|
||||
{
|
||||
#[inline]
|
||||
pub fn default(cputype: M68kType, data_width: u8) -> Self {
|
||||
Self {
|
||||
|
@ -42,7 +48,7 @@ impl M68kCycle {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new(cpu: &M68k, clock: Instant) -> Self {
|
||||
pub fn new(cpu: &M68k<Instant>, clock: Instant) -> Self {
|
||||
let is_supervisor = cpu.state.sr & (Flags::Supervisor as u16) != 0;
|
||||
Self {
|
||||
decoder: M68kDecoder::new(cpu.info.chip, is_supervisor, cpu.state.pc),
|
||||
|
@ -53,17 +59,11 @@ impl M68kCycle {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn begin<Bus>(self, cpu: &mut M68k, bus: Bus) -> M68kCycleExecutor<'_, Bus>
|
||||
pub fn begin<Bus>(self, cpu: &mut M68k<Instant>, bus: Bus) -> M68kCycleExecutor<'_, Bus, Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant>,
|
||||
{
|
||||
cpu.stats.cycle_number += 1;
|
||||
if cpu.stats.cycle_number > cpu.stats.last_update {
|
||||
cpu.stats.last_update += 1_000_000;
|
||||
let now = std::time::SystemTime::now();
|
||||
log::warn!("{} per million", now.duration_since(cpu.stats.last_time).unwrap().as_micros());
|
||||
cpu.stats.last_time = now;
|
||||
}
|
||||
cpu.stats.cycle_number = cpu.stats.cycle_number.wrapping_add(1);
|
||||
|
||||
M68kCycleExecutor {
|
||||
state: &mut cpu.state,
|
||||
|
@ -74,10 +74,11 @@ impl M68kCycle {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Bus, BusError> Step<M68kAddress, Instant, Bus> for M68k
|
||||
impl<Bus, BusError, Instant> Step<M68kAddress, Instant, Bus> for M68k<Instant>
|
||||
where
|
||||
BusError: bus::Error,
|
||||
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||
BusError: bus::Error,
|
||||
Instant: time::Instant,
|
||||
{
|
||||
type Error = M68kError<BusError>;
|
||||
|
||||
|
@ -107,28 +108,30 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct M68kCycleExecutor<'a, Bus>
|
||||
pub struct M68kCycleExecutor<'a, Bus, Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant>,
|
||||
{
|
||||
pub state: &'a mut M68kState,
|
||||
pub bus: Bus,
|
||||
pub debugger: &'a mut M68kDebugger,
|
||||
pub cycle: M68kCycle,
|
||||
pub cycle: M68kCycle<Instant>,
|
||||
}
|
||||
|
||||
impl<'a, Bus> M68kCycleExecutor<'a, Bus>
|
||||
impl<'a, Bus, Instant> M68kCycleExecutor<'a, Bus, Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant>,
|
||||
Instant: Copy,
|
||||
{
|
||||
pub fn end(self) -> M68kCycle {
|
||||
pub fn end(self) -> M68kCycle<Instant> {
|
||||
self.cycle
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Bus> M68kCycleExecutor<'a, Bus>
|
||||
impl<'a, Bus, Instant> M68kCycleExecutor<'a, Bus, Instant>
|
||||
where
|
||||
Bus: BusAccess<M68kAddress, Instant>,
|
||||
Instant: Copy,
|
||||
{
|
||||
#[inline]
|
||||
pub fn step(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||
|
|
|
@ -11,5 +11,11 @@ pub mod timing;
|
|||
#[cfg(feature = "moa")]
|
||||
pub mod moa;
|
||||
|
||||
pub use crate::state::{M68k, M68kType, M68kError};
|
||||
pub use crate::memory::{M68kAddress, M68kAddressSpace};
|
||||
pub use crate::assembler::M68kAssembler;
|
||||
pub use crate::debugger::M68kDebugger;
|
||||
pub use crate::state::{M68k, M68kType, M68kState, M68kError, CpuInfo, Exceptions};
|
||||
pub use crate::memory::{M68kAddress, M68kAddressSpace, M68kBusPort};
|
||||
pub use crate::decode::{M68kDecoder, InstructionDecoding};
|
||||
pub use crate::execute::{M68kCycle, M68kCycleExecutor};
|
||||
pub use crate::timing::M68kInstructionTiming;
|
||||
//pub use crate::instructions::{Instruction, Target, Size, Sign, XRegister, BaseRegister, IndexRegister, Direction};
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use core::cmp;
|
||||
use core::fmt::Write;
|
||||
use femtos::Instant;
|
||||
use emulator_hal::time;
|
||||
use emulator_hal::bus::BusAccess;
|
||||
|
||||
use crate::state::{M68k, M68kError, CpuInfo, Exceptions};
|
||||
use crate::{M68kError, CpuInfo};
|
||||
use crate::state::Exceptions;
|
||||
use crate::instructions::Size;
|
||||
|
||||
#[repr(u8)]
|
||||
|
@ -35,7 +36,7 @@ pub enum MemAccess {
|
|||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
// TODO change to MemoryState or RequestState or AccessState or maybe even BusState
|
||||
pub struct MemoryRequest {
|
||||
pub struct MemoryRequest<Instant> {
|
||||
pub i_n_bit: bool,
|
||||
pub access: MemAccess,
|
||||
pub code: FunctionCode,
|
||||
|
@ -62,7 +63,10 @@ impl FunctionCode {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for MemoryRequest {
|
||||
impl<Instant> Default for MemoryRequest<Instant>
|
||||
where
|
||||
Instant: time::Instant,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
i_n_bit: false,
|
||||
|
@ -75,7 +79,18 @@ impl Default for MemoryRequest {
|
|||
}
|
||||
}
|
||||
|
||||
impl MemoryRequest {
|
||||
impl<Instant> MemoryRequest<Instant> {
|
||||
fn new(clock: Instant) -> Self {
|
||||
Self {
|
||||
i_n_bit: false,
|
||||
access: MemAccess::Read,
|
||||
code: FunctionCode::Reserved0,
|
||||
size: Size::Word,
|
||||
address: 0,
|
||||
clock,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn instruction<BusError>(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, M68kError<BusError>> {
|
||||
self.i_n_bit = false;
|
||||
self.code = FunctionCode::program(is_supervisor);
|
||||
|
@ -106,14 +121,14 @@ pub type M68kAddress = u32;
|
|||
pub type M68kAddressSpace = (FunctionCode, u32);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct InstructionRequest {
|
||||
pub request: MemoryRequest,
|
||||
pub struct InstructionRequest<Instant> {
|
||||
pub request: MemoryRequest<Instant>,
|
||||
pub current_clock: Instant,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct M68kBusPort {
|
||||
pub request: MemoryRequest,
|
||||
pub struct M68kBusPort<Instant> {
|
||||
pub request: MemoryRequest<Instant>,
|
||||
pub data_bytewidth: usize,
|
||||
pub address_mask: u32,
|
||||
pub cycle_start_clock: Instant,
|
||||
|
@ -121,11 +136,10 @@ pub struct M68kBusPort {
|
|||
}
|
||||
|
||||
|
||||
impl M68k {
|
||||
// TODO should some of the ones from execute.rs move here
|
||||
}
|
||||
|
||||
impl Default for M68kBusPort {
|
||||
impl<Instant> Default for M68kBusPort<Instant>
|
||||
where
|
||||
Instant: time::Instant,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
request: Default::default(),
|
||||
|
@ -137,10 +151,13 @@ impl Default for M68kBusPort {
|
|||
}
|
||||
}
|
||||
|
||||
impl M68kBusPort {
|
||||
impl<Instant> M68kBusPort<Instant>
|
||||
where
|
||||
Instant: Copy,
|
||||
{
|
||||
pub fn from_info(info: &CpuInfo, clock: Instant) -> Self {
|
||||
Self {
|
||||
request: Default::default(),
|
||||
request: MemoryRequest::new(clock),
|
||||
data_bytewidth: info.data_width as usize / 8,
|
||||
address_mask: 1_u32.checked_shl(info.address_width as u32).unwrap_or(0).wrapping_sub(1),
|
||||
cycle_start_clock: clock,
|
||||
|
|
|
@ -3,11 +3,9 @@ use emulator_hal::bus;
|
|||
|
||||
use moa_core::{System, Error, Address, Steppable, Interruptable, Addressable, Debuggable, Transmutable};
|
||||
|
||||
use crate::state::{M68k, M68kError};
|
||||
use crate::decode::M68kDecoder;
|
||||
use crate::execute::M68kCycle;
|
||||
use crate::{M68k, M68kError, M68kDecoder, M68kCycle, M68kBusPort};
|
||||
|
||||
impl Steppable for M68k {
|
||||
impl Steppable for M68k<Instant> {
|
||||
fn step(&mut self, system: &System) -> Result<Duration, Error> {
|
||||
let cycle = M68kCycle::new(self, system.clock);
|
||||
|
||||
|
@ -36,9 +34,9 @@ impl Steppable for M68k {
|
|||
}
|
||||
}
|
||||
|
||||
impl Interruptable for M68k {}
|
||||
impl Interruptable for M68k<Instant> {}
|
||||
|
||||
impl Transmutable for M68k {
|
||||
impl Transmutable for M68k<Instant> {
|
||||
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
||||
Some(self)
|
||||
}
|
||||
|
@ -77,7 +75,7 @@ impl<BusError: bus::Error> From<M68kError<BusError>> for Error {
|
|||
}
|
||||
|
||||
|
||||
impl Debuggable for M68k {
|
||||
impl Debuggable for M68k<Instant> {
|
||||
fn add_breakpoint(&mut self, addr: Address) {
|
||||
self.debugger.breakpoints.push(addr as u32);
|
||||
}
|
||||
|
@ -98,12 +96,13 @@ impl Debuggable for M68k {
|
|||
|
||||
fn print_disassembly(&mut self, system: &System, addr: Address, count: usize) {
|
||||
let mut decoder = M68kDecoder::new(self.info.chip, true, 0);
|
||||
let mut memory = M68kBusPort::from_info(&self.info, system.clock);
|
||||
|
||||
let mut bus = system.bus.borrow_mut();
|
||||
let mut adapter: bus::BusAdapter<u32, u64, Instant, &mut dyn Addressable, Error> =
|
||||
bus::BusAdapter::new(&mut *bus, |addr| addr as u64, |err| err);
|
||||
|
||||
decoder.dump_disassembly(&mut adapter, addr as u32, count as u32);
|
||||
decoder.dump_disassembly(&mut adapter, &mut memory, addr as u32, count as u32);
|
||||
}
|
||||
|
||||
fn run_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use core::fmt::{self, Write};
|
||||
use femtos::{Duration, Frequency};
|
||||
// m68k CPU State
|
||||
|
||||
use crate::debugger::M68kDebugger;
|
||||
use femtos::Frequency;
|
||||
use core::fmt::{self, Write};
|
||||
use emulator_hal::time;
|
||||
|
||||
use crate::{M68kDebugger, M68kCycle};
|
||||
use crate::instructions::Target;
|
||||
use crate::execute::M68kCycle;
|
||||
|
||||
|
||||
pub type ClockCycles = u16;
|
||||
|
@ -195,27 +197,23 @@ pub enum M68kError<BusError> {
|
|||
#[derive(Clone)]
|
||||
pub struct M68kStatistics {
|
||||
pub cycle_number: usize,
|
||||
pub last_update: usize,
|
||||
pub last_time: std::time::SystemTime,
|
||||
}
|
||||
|
||||
impl Default for M68kStatistics {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cycle_number: 0,
|
||||
last_update: 0,
|
||||
last_time: std::time::SystemTime::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct M68k {
|
||||
pub struct M68k<Instant> {
|
||||
pub info: CpuInfo,
|
||||
pub state: M68kState,
|
||||
pub debugger: M68kDebugger,
|
||||
pub stats: M68kStatistics,
|
||||
pub cycle: Option<M68kCycle>,
|
||||
pub cycle: Option<M68kCycle<Instant>>,
|
||||
}
|
||||
|
||||
impl Default for M68kState {
|
||||
|
@ -251,7 +249,10 @@ impl M68kState {
|
|||
}
|
||||
}
|
||||
|
||||
impl M68k {
|
||||
impl<Instant> M68k<Instant>
|
||||
where
|
||||
Instant: time::Instant,
|
||||
{
|
||||
pub fn new(info: CpuInfo) -> Self {
|
||||
M68k {
|
||||
info,
|
||||
|
@ -279,9 +280,10 @@ impl M68k {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn last_cycle_duration(&self) -> Duration {
|
||||
pub fn last_cycle_duration(&self) -> Instant::Duration {
|
||||
let clocks = self.cycle.as_ref().map(|cycle| cycle.timing.calculate_clocks()).unwrap_or(4);
|
||||
self.info.frequency.period_duration() * clocks as u64
|
||||
//self.info.frequency.period_duration() * clocks as u64
|
||||
Instant::hertz_to_duration(self.info.frequency.as_hz() as u64) * clocks as u32
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// m68k Instruction Timing Calclator
|
||||
|
||||
use crate::M68kType;
|
||||
use crate::state::ClockCycles;
|
||||
use crate::instructions::{Size, Sign, Direction, Target, Instruction};
|
||||
|
|
|
@ -145,7 +145,7 @@ pub fn run_system_for(handle: &mut SystemHandle, nanos: u32) -> usize {
|
|||
log::error!("{:?}", err);
|
||||
}
|
||||
let run_time = run_timer.elapsed().as_millis();
|
||||
log::debug!("ran simulation for {:?}ms in {:?}ms", nanoseconds_per_frame / 1_000_000, run_time);
|
||||
log::debug!("ran simulation for {:?}ms in {:?}ms", nanoseconds_per_frame / 1_000_000_u32, run_time);
|
||||
run_time as usize
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,7 @@ fn update(emulator: Rc<RefCell<Emulator>>) {
|
|||
log::error!("{:?}", err);
|
||||
}
|
||||
let run_time = run_timer.elapsed().as_millis();
|
||||
log::debug!("ran simulation for {:?}ms in {:?}ms", nanoseconds_per_frame / 1_000_000, run_time);
|
||||
log::debug!("ran simulation for {:?}ms in {:?}ms", nanoseconds_per_frame / 1_000_000_u32, run_time);
|
||||
|
||||
let running = emulator.borrow().running;
|
||||
if running {
|
||||
|
|
|
@ -768,7 +768,7 @@ impl Steppable for Ym7101 {
|
|||
});
|
||||
}
|
||||
|
||||
Ok(Frequency::from_hz(13_423_294).period_duration() * 4)
|
||||
Ok(Frequency::from_hz(13_423_294).period_duration() * 4_u32)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ impl TestCase {
|
|||
|
||||
|
||||
#[allow(clippy::uninit_vec)]
|
||||
fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, MemoryBlock<u32, Instant>), Error> {
|
||||
fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k<Instant>, MemoryBlock<u32, Instant>), Error> {
|
||||
// Insert basic initialization
|
||||
let len = 0x100_0000;
|
||||
let mut data = Vec::with_capacity(len);
|
||||
|
@ -174,7 +174,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn load_state(cpu: &mut M68k, memory: &mut MemoryBlock<u32, Instant>, initial: &TestState) -> Result<(), Error> {
|
||||
fn load_state(cpu: &mut M68k<Instant>, 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;
|
||||
|
@ -213,7 +213,7 @@ fn load_state(cpu: &mut M68k, memory: &mut MemoryBlock<u32, Instant>, initial: &
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn assert_state(cpu: &M68k, memory: &mut MemoryBlock<u32, Instant>, expected: &TestState) -> Result<(), Error> {
|
||||
fn assert_state(cpu: &M68k<Instant>, 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")?;
|
||||
|
@ -258,7 +258,7 @@ fn assert_state(cpu: &M68k, memory: &mut MemoryBlock<u32, Instant>, expected: &T
|
|||
}
|
||||
|
||||
fn step_cpu_and_assert(
|
||||
cpu: &mut M68k,
|
||||
cpu: &mut M68k<Instant>,
|
||||
memory: &mut MemoryBlock<u32, Instant>,
|
||||
case: &TestCase,
|
||||
test_timing: bool,
|
||||
|
|
10
todo.txt
10
todo.txt
|
@ -1,7 +1,11 @@
|
|||
|
||||
* implement Inspect/Debug traits
|
||||
* fix dump_state everywhere, which now requires a writer. Is there an easier way? Is there a way that doesn't require std
|
||||
* decide if you should continue expecting Instant to usable through the trait alone, despite issues
|
||||
* fix it to use the full 68k address space, and maybe see if it's possible to make the address translation cleaner/nicer/simpler/faster
|
||||
* now that you have Instant as generic in m68k, try making it an associated type to see if it's possible to hide it away
|
||||
|
||||
* try using the debug and inspect traits elsewhere in moa
|
||||
* convert all code to use fmt::Writer instead of println
|
||||
|
||||
* figure out how to do interrupts, and add them to emulator-hal, implement them in m68k
|
||||
* convert the Z80
|
||||
* convert peripherals to use BusAccess and Step
|
||||
|
@ -15,6 +19,8 @@
|
|||
|
||||
-----
|
||||
|
||||
* add pub use for all the pub types to the lib.rs of the m68k crate
|
||||
|
||||
* there are many issues with the coprocessor address space, and the VDP
|
||||
* I mapped the sn sound chip into 0xC00010, in the middle of the VDP's address space, and didn't get a runtime error!!! needs fixing
|
||||
* there should be a better way of aliasing addresses. Can you make the actual Z80 bus get mapped into 0xA00000?
|
||||
|
|
Loading…
Reference in New Issue