mirror of
https://github.com/transistorfet/moa.git
synced 2024-12-21 20:29:22 +00:00
Implemented Inspect and Debug traits from emulator-hal (#5)
* Implemented Inspect and Debug traits from emulator-hal * Updated emulator-hal submodule * Updated Cargo.lock * Fixed missing feature flag and clippy * Fixed tests
This commit is contained in:
parent
5cd1111fc7
commit
97aef5d357
23
Cargo.lock
generated
23
Cargo.lock
generated
@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37fe60779335388a88c01ac6c3be40304d1e349de3ada3b15f7808bb90fa9dce"
|
||||
dependencies = [
|
||||
"alsa-sys",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -109,7 +109,7 @@ version = "0.69.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
@ -131,9 +131,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.2"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
@ -390,6 +390,9 @@ checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
[[package]]
|
||||
name = "emulator-hal"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"femtos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "emulator-hal-memory"
|
||||
@ -422,9 +425,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||
|
||||
[[package]]
|
||||
name = "femtos"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b90ac969e2dfcc103ec34948f65290b7616edc460922bd6d33ad75f525964f7d"
|
||||
checksum = "18a32780032dcd040247c5bad84fae37c48b0d6d4d15cf70d696566740f81959"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
@ -694,7 +697,7 @@ version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
@ -1004,7 +1007,7 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"jni-sys",
|
||||
"log",
|
||||
"ndk-sys",
|
||||
@ -1045,7 +1048,7 @@ version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
@ -1312,7 +1315,7 @@ version = "0.38.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
|
@ -8,7 +8,7 @@ log = "0.4"
|
||||
thiserror = "1.0"
|
||||
femtos = "0.1"
|
||||
moa-parsing = { path = "../../libraries/parsing" }
|
||||
emulator-hal = { path = "../../libraries/emulator-hal/emulator-hal" }
|
||||
emulator-hal = { path = "../../libraries/emulator-hal/emulator-hal", features = ["femtos"] }
|
||||
|
||||
moa-core = { path = "../../core", optional = true }
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
fn remove_breakpoint(&mut self, address: M68kAddress) {
|
||||
if let Some(index) = self.debugger.breakpoints.iter().position(|a| *a == address) {
|
||||
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;
|
||||
@ -192,30 +194,18 @@ pub enum M68kError<BusError> {
|
||||
Other(String),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
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 +241,10 @@ impl M68kState {
|
||||
}
|
||||
}
|
||||
|
||||
impl M68k {
|
||||
impl<Instant> M68k<Instant>
|
||||
where
|
||||
Instant: time::Instant,
|
||||
{
|
||||
pub fn new(info: CpuInfo) -> Self {
|
||||
M68k {
|
||||
info,
|
||||
@ -279,9 +272,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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ mod decode_unit_tests {
|
||||
|
||||
fn run_decode_test<F>(cputype: M68kType, mut test_func: F)
|
||||
where
|
||||
F: FnMut(&mut InstructionDecoding<'_, MemoryBlock<u32, Instant>>),
|
||||
F: FnMut(&mut InstructionDecoding<'_, MemoryBlock<u32, Instant>, Instant>),
|
||||
{
|
||||
let mut memory = MemoryBlock::from(vec![0; 0x0000100]);
|
||||
let mut decoder = M68kDecoder::new(cputype, true, 0);
|
||||
@ -330,7 +330,7 @@ mod execute_unit_tests {
|
||||
#[allow(clippy::uninit_vec)]
|
||||
fn run_execute_test<F>(cputype: M68kType, mut test_func: F)
|
||||
where
|
||||
F: FnMut(M68kCycleExecutor<&mut MemoryBlock<u32, Instant>>),
|
||||
F: FnMut(M68kCycleExecutor<&mut MemoryBlock<u32, Instant>, Instant>),
|
||||
{
|
||||
// Insert basic initialization
|
||||
let len = 0x10_0000;
|
||||
|
@ -1,3 +1,5 @@
|
||||
// m68k Instruction Timing Calclator
|
||||
|
||||
use crate::M68kType;
|
||||
use crate::state::ClockCycles;
|
||||
use crate::instructions::{Size, Sign, Direction, Target, Instruction};
|
||||
|
@ -64,7 +64,7 @@ const DECODE_TESTS: &'static [TestCase] = &[
|
||||
];
|
||||
|
||||
|
||||
fn init_decode_test(cputype: M68kType) -> (M68k, M68kCycle, MemoryBlock<u32, Instant>) {
|
||||
fn init_decode_test(cputype: M68kType) -> (M68k<Instant>, M68kCycle<Instant>, MemoryBlock<u32, Instant>) {
|
||||
// Insert basic initialization
|
||||
let len = 0x2000;
|
||||
let mut data = Vec::with_capacity(len);
|
||||
|
@ -38,7 +38,7 @@ struct TestCase {
|
||||
#[allow(clippy::uninit_vec)]
|
||||
fn run_execute_test<F>(cputype: M68kType, mut test_func: F)
|
||||
where
|
||||
F: FnMut(M68kCycleExecutor<&mut MemoryBlock<u32, Instant>>),
|
||||
F: FnMut(M68kCycleExecutor<&mut MemoryBlock<u32, Instant>, Instant>),
|
||||
{
|
||||
// Insert basic initialization
|
||||
let len = 0x10_0000;
|
||||
|
@ -12,7 +12,7 @@ const INIT_STACK: M68kAddress = 0x00002000;
|
||||
const INIT_ADDR: M68kAddress = 0x00000010;
|
||||
|
||||
#[allow(clippy::uninit_vec)]
|
||||
fn init_decode_test(cputype: M68kType) -> (M68k, M68kCycle, MemoryBlock<u32, Instant>) {
|
||||
fn init_decode_test(cputype: M68kType) -> (M68k<Instant>, M68kCycle<Instant>, MemoryBlock<u32, Instant>) {
|
||||
// Insert basic initialization
|
||||
let len = 0x10_0000;
|
||||
let mut data = Vec::with_capacity(len);
|
||||
|
@ -26,7 +26,7 @@ const TIMING_TESTS: &'static [TimingCase] = &[TimingCase {
|
||||
}];
|
||||
|
||||
|
||||
fn init_decode_test(cputype: M68kType) -> (M68k, M68kCycle, MemoryBlock<u32, Instant>) {
|
||||
fn init_decode_test(cputype: M68kType) -> (M68k<Instant>, M68kCycle<Instant>, MemoryBlock<u32, Instant>) {
|
||||
// Insert basic initialization
|
||||
let len = 0x10_0000;
|
||||
let mut data = Vec::with_capacity(len);
|
||||
|
29
emulator/frontends/pixels/Cargo.lock
generated
29
emulator/frontends/pixels/Cargo.lock
generated
@ -67,7 +67,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37fe60779335388a88c01ac6c3be40304d1e349de3ada3b15f7808bb90fa9dce"
|
||||
dependencies = [
|
||||
"alsa-sys",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -162,7 +162,7 @@ version = "0.69.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
@ -199,9 +199,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.2"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
@ -493,6 +493,9 @@ checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
[[package]]
|
||||
name = "emulator-hal"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"femtos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
@ -524,9 +527,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "femtos"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b90ac969e2dfcc103ec34948f65290b7616edc460922bd6d33ad75f525964f7d"
|
||||
checksum = "18a32780032dcd040247c5bad84fae37c48b0d6d4d15cf70d696566740f81959"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
@ -615,7 +618,7 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"gpu-descriptor-types",
|
||||
"hashbrown 0.14.3",
|
||||
]
|
||||
@ -626,7 +629,7 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -825,7 +828,7 @@ version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"libc",
|
||||
"redox_syscall 0.4.1",
|
||||
]
|
||||
@ -1091,7 +1094,7 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"jni-sys",
|
||||
"log",
|
||||
"ndk-sys 0.5.0+25.2.9519653",
|
||||
@ -1987,7 +1990,7 @@ checksum = "8f478237b4bf0d5b70a39898a66fa67ca3a007d79f2520485b8b0c3dfc46f8c2"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-vec",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"codespan-reporting",
|
||||
"log",
|
||||
"naga",
|
||||
@ -2012,7 +2015,7 @@ dependencies = [
|
||||
"arrayvec",
|
||||
"ash",
|
||||
"bit-set",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"block",
|
||||
"core-graphics-types",
|
||||
"d3d12",
|
||||
@ -2050,7 +2053,7 @@ version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0c153280bb108c2979eb5c7391cb18c56642dd3c072e55f52065e13e2a1252a"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"js-sys",
|
||||
"web-sys",
|
||||
]
|
||||
|
@ -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 {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 84e665ce5749187d0c323f77971c288d0964fa96
|
||||
Subproject commit 10000669524747dce101947e60f230551b26f6f8
|
@ -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
Block a user