diff --git a/Cargo.lock b/Cargo.lock index ec0b028..d71adab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -417,6 +417,10 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "emulator-hal" +version = "0.1.0" + [[package]] name = "env_logger" version = "0.8.4" @@ -763,6 +767,7 @@ dependencies = [ name = "moa-core" version = "0.1.0" dependencies = [ + "emulator-hal", "femtos", "log", "moa-host", @@ -788,6 +793,7 @@ dependencies = [ name = "moa-m68k" version = "0.1.0" dependencies = [ + "emulator-hal", "femtos", "log", "moa-core", @@ -935,10 +941,12 @@ dependencies = [ name = "moa-z80" version = "0.1.0" dependencies = [ + "emulator-hal", "femtos", "log", "moa-core", "moa-signals", + "thiserror", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f78450f..7450c3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,9 @@ exclude = [ ] default-members = ["emulator/frontends/minifb"] +[profile.dev] +opt-level = 3 + [profile.release] debug = true #overflow-checks = true diff --git a/emulator/core/Cargo.toml b/emulator/core/Cargo.toml index 8460ec6..c3cb2e7 100644 --- a/emulator/core/Cargo.toml +++ b/emulator/core/Cargo.toml @@ -8,3 +8,4 @@ log = "0.4" femtos = "0.1" thiserror = "1.0" moa-host = { path = "../libraries/host" } +emulator-hal = { path = "/media/work/projects/emulator-hal/emulator-hal" } diff --git a/emulator/core/src/lib.rs b/emulator/core/src/lib.rs index f718345..69c5571 100644 --- a/emulator/core/src/lib.rs +++ b/emulator/core/src/lib.rs @@ -14,3 +14,5 @@ pub use crate::interrupts::InterruptController; pub use crate::memory::{MemoryBlock, AddressTranslator, AddressRepeater, Bus, BusPort, dump_slice}; pub use crate::system::System; +pub use emulator_hal::bus::{BusAccess}; + diff --git a/emulator/core/src/system.rs b/emulator/core/src/system.rs index f6113f7..87a00e5 100644 --- a/emulator/core/src/system.rs +++ b/emulator/core/src/system.rs @@ -210,3 +210,26 @@ impl NextStep { } } +/* +use emulator_hal::bus::{BusType, BusAccess}; + +impl BusType for System { + type Address = u64; + type Error = Error; + type Instant = Instant; +} + +impl BusAccess for System { + fn read(&mut self, _now: Instant, addr: u64, data: &mut [u8]) -> Result { + let addr = addr as usize; + data.copy_from_slice(&self.0[addr..addr + data.len()]); + Ok(data.len()) + } + + fn write(&mut self, _now: Instant, addr: u64, data: &[u8]) -> Result { + let addr = addr as usize; + self.0[addr..addr + data.len()].copy_from_slice(data); + Ok(data.len()) + } +} +*/ diff --git a/emulator/cpus/m68k/Cargo.toml b/emulator/cpus/m68k/Cargo.toml index e6ae8d6..483a72f 100644 --- a/emulator/cpus/m68k/Cargo.toml +++ b/emulator/cpus/m68k/Cargo.toml @@ -9,3 +9,4 @@ thiserror = "1.0" femtos = "0.1" moa-core = { path = "../../core" } moa-parsing = { path = "../../libraries/parsing" } +emulator-hal = { path = "/media/work/projects/emulator-hal/emulator-hal" } diff --git a/emulator/cpus/m68k/src/debugger.rs b/emulator/cpus/m68k/src/debugger.rs index 203ed1f..c6cd442 100644 --- a/emulator/cpus/m68k/src/debugger.rs +++ b/emulator/cpus/m68k/src/debugger.rs @@ -3,6 +3,7 @@ use moa_core::{System, Error, Address, Addressable, Debuggable}; use super::state::M68k; use super::decode::M68kDecoder; +use super::execute::M68kCycleGuard; #[derive(Clone, Default)] pub struct StackTracer { @@ -40,9 +41,10 @@ impl Debuggable for M68k { } fn print_current_step(&mut self, _system: &System) -> Result<(), Error> { - let _ = self.decoder.decode_at(&mut self.port, true, self.state.pc); - self.decoder.dump_decoded(&mut self.port); - self.dump_state(); + // 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); + //self.dump_state(); Ok(()) } @@ -68,7 +70,7 @@ impl Debuggable for M68k { } } -impl M68k { +impl<'a> M68kCycleGuard<'a> { pub fn check_breakpoints(&mut self) -> Result<(), Error> { for breakpoint in &self.debugger.breakpoints { if *breakpoint == self.state.pc { diff --git a/emulator/cpus/m68k/src/decode.rs b/emulator/cpus/m68k/src/decode.rs index e7c9bbc..4cdd772 100644 --- a/emulator/cpus/m68k/src/decode.rs +++ b/emulator/cpus/m68k/src/decode.rs @@ -37,7 +37,7 @@ const OPCG_SHIFT: u8 = 0xE; const OPCG_FLINE: u8 = 0xF; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct M68kDecoder { pub cputype: M68kType, pub is_supervisor: bool, @@ -66,45 +66,45 @@ impl M68kDecoder { self.end = start; } - pub fn decode_at(&mut self, memory: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError> { + pub fn decode_at(&mut self, bus: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError> { self.init(is_supervisor, start); - self.instruction = self.decode_next(memory)?; + self.instruction = self.decode_next(bus)?; Ok(()) } - pub fn decode_next(&mut self, memory: &mut M68kBusPort) -> Result { - let ins = self.read_instruction_word(memory)?; + pub fn decode_next(&mut self, bus: &mut M68kBusPort) -> Result { + let ins = self.read_instruction_word(bus)?; self.instruction_word = ins; match ((ins & 0xF000) >> 12) as u8 { - OPCG_BIT_OPS => self.decode_group_bit_ops(memory, ins), - OPCG_MOVE_BYTE => self.decode_group_move_byte(memory, ins), - OPCG_MOVE_LONG => self.decode_group_move_long(memory, ins), - OPCG_MOVE_WORD => self.decode_group_move_word(memory, ins), - OPCG_MISC => self.decode_group_misc(memory, ins), - OPCG_ADDQ_SUBQ => self.decode_group_addq_subq(memory, ins), - OPCG_BRANCH => self.decode_group_branch(memory, ins), - OPCG_MOVEQ => self.decode_group_moveq(memory, ins), - OPCG_DIV_OR => self.decode_group_div_or(memory, ins), - OPCG_SUB => self.decode_group_sub(memory, ins), + OPCG_BIT_OPS => self.decode_group_bit_ops(bus, ins), + OPCG_MOVE_BYTE => self.decode_group_move_byte(bus, ins), + OPCG_MOVE_LONG => self.decode_group_move_long(bus, ins), + OPCG_MOVE_WORD => self.decode_group_move_word(bus, ins), + OPCG_MISC => self.decode_group_misc(bus, ins), + OPCG_ADDQ_SUBQ => self.decode_group_addq_subq(bus, ins), + OPCG_BRANCH => self.decode_group_branch(bus, ins), + OPCG_MOVEQ => self.decode_group_moveq(bus, ins), + OPCG_DIV_OR => self.decode_group_div_or(bus, ins), + OPCG_SUB => self.decode_group_sub(bus, ins), OPCG_ALINE => Ok(Instruction::UnimplementedA(ins)), - OPCG_CMP_EOR => self.decode_group_cmp_eor(memory, ins), - OPCG_MUL_AND => self.decode_group_mul_and(memory, ins), - OPCG_ADD => self.decode_group_add(memory, ins), - OPCG_SHIFT => self.decode_group_shift(memory, ins), + OPCG_CMP_EOR => self.decode_group_cmp_eor(bus, ins), + OPCG_MUL_AND => self.decode_group_mul_and(bus, ins), + OPCG_ADD => self.decode_group_add(bus, ins), + OPCG_SHIFT => self.decode_group_shift(bus, ins), OPCG_FLINE => Ok(Instruction::UnimplementedF(ins)), _ => Err(M68kError::Exception(Exceptions::IllegalInstruction)), } } #[inline] - fn decode_group_bit_ops(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_bit_ops(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { let optype = (ins & 0x0F00) >> 8; if (ins & 0x13F) == 0x03C { match (ins & 0x00C0) >> 6 { 0b00 => { - let data = self.read_instruction_word(memory)?; + let data = self.read_instruction_word(bus)?; match optype { 0b0000 => Ok(Instruction::ORtoCCR(data as u8)), 0b0010 => Ok(Instruction::ANDtoCCR(data as u8)), @@ -113,7 +113,7 @@ impl M68kDecoder { } }, 0b01 => { - let data = self.read_instruction_word(memory)?; + let data = self.read_instruction_word(bus)?; match optype { 0b0000 => Ok(Instruction::ORtoSR(data)), 0b0010 => Ok(Instruction::ANDtoSR(data)), @@ -128,16 +128,16 @@ impl M68kDecoder { let areg = get_low_reg(ins); let dir = if (ins & 0x0080) == 0 { Direction::FromTarget } else { Direction::ToTarget }; let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; - let offset = self.read_instruction_word(memory)? as i16; + let offset = self.read_instruction_word(bus)? as i16; Ok(Instruction::MOVEP(dreg, areg, offset, size, dir)) } else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 { let bitnum = if (ins & 0x0100) == 0x0100 { Target::DirectDReg(get_high_reg(ins)) } else { - Target::Immediate(self.read_instruction_word(memory)? as u32) + Target::Immediate(self.read_instruction_word(bus)? as u32) }; - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; + let target = self.decode_lower_effective_address(bus, ins, Some(Size::Byte))?; let size = match target { Target::DirectAReg(_) | Target::DirectDReg(_) => Size::Long, _ => Size::Byte, @@ -153,12 +153,12 @@ impl M68kDecoder { } else { let size = get_size(ins); let data = match size { - Some(Size::Byte) => self.read_instruction_word(memory)? as u32 & 0xFF, - Some(Size::Word) => self.read_instruction_word(memory)? as u32, - Some(Size::Long) => self.read_instruction_long(memory)?, + Some(Size::Byte) => self.read_instruction_word(bus)? as u32 & 0xFF, + Some(Size::Word) => self.read_instruction_word(bus)? as u32, + Some(Size::Long) => self.read_instruction_long(bus)?, None => return Err(M68kError::Exception(Exceptions::IllegalInstruction)), }; - let target = self.decode_lower_effective_address(memory, ins, size)?; + let target = self.decode_lower_effective_address(bus, ins, size)?; match optype { 0b0000 => Ok(Instruction::OR(Target::Immediate(data), target, size.unwrap())), @@ -173,16 +173,16 @@ impl M68kDecoder { } #[inline] - fn decode_group_move_byte(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { - let src = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; - let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Byte))?; + fn decode_group_move_byte(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { + let src = self.decode_lower_effective_address(bus, ins, Some(Size::Byte))?; + let dest = self.decode_upper_effective_address(bus, ins, Some(Size::Byte))?; Ok(Instruction::MOVE(src, dest, Size::Byte)) } #[inline] - fn decode_group_move_long(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { - let src = self.decode_lower_effective_address(memory, ins, Some(Size::Long))?; - let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Long))?; + fn decode_group_move_long(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { + let src = self.decode_lower_effective_address(bus, ins, Some(Size::Long))?; + let dest = self.decode_upper_effective_address(bus, ins, Some(Size::Long))?; if let Target::DirectAReg(reg) = dest { Ok(Instruction::MOVEA(src, reg, Size::Long)) } else { @@ -191,9 +191,9 @@ impl M68kDecoder { } #[inline] - fn decode_group_move_word(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { - let src = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; - let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Word))?; + fn decode_group_move_word(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { + let src = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; + let dest = self.decode_upper_effective_address(bus, ins, Some(Size::Word))?; if let Target::DirectAReg(reg) = dest { Ok(Instruction::MOVEA(src, reg, Size::Word)) } else { @@ -202,7 +202,7 @@ impl M68kDecoder { } #[inline] - fn decode_group_misc(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_misc(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { let ins_0f00 = ins & 0xF00; let ins_00f0 = ins & 0x0F0; @@ -217,31 +217,31 @@ impl M68kDecoder { }; let reg = get_high_reg(ins); - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; Ok(Instruction::CHK(target, reg, size)) } else { - let src = self.decode_lower_effective_address(memory, ins, None)?; + let src = self.decode_lower_effective_address(bus, ins, None)?; let dest = get_high_reg(ins); Ok(Instruction::LEA(src, dest)) } } else if (ins & 0xB80) == 0x880 && (ins & 0x038) != 0 { let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; - let data = self.read_instruction_word(memory)?; - let target = self.decode_lower_effective_address(memory, ins, None)?; + let data = self.read_instruction_word(bus)?; + let target = self.decode_lower_effective_address(bus, ins, None)?; let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget }; Ok(Instruction::MOVEM(target, size, dir, data)) } else if (ins & 0xF80) == 0xC00 && self.cputype >= M68kType::MC68020 { - let extension = self.read_instruction_word(memory)?; + let extension = self.read_instruction_word(bus)?; let reg_h = if (extension & 0x0400) != 0 { Some(get_low_reg(ins)) } else { None }; let reg_l = ((extension & 0x7000) >> 12) as u8; - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Long))?; + let target = self.decode_lower_effective_address(bus, ins, Some(Size::Long))?; let sign = if (ins & 0x0800) == 0 { Sign::Unsigned } else { Sign::Signed }; match (ins & 0x040) == 0 { true => Ok(Instruction::MULL(target, reg_h, reg_l, sign)), false => Ok(Instruction::DIVL(target, reg_h, reg_l, sign)), } } else if (ins & 0x800) == 0 { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + let target = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; match (ins & 0x0700) >> 8 { 0b000 => { match get_size(ins) { @@ -275,11 +275,11 @@ impl M68kDecoder { let mode = get_low_mode(ins); match (opmode, mode) { (0b000, 0b001) if self.cputype >= M68kType::MC68020 => { - let data = self.read_instruction_long(memory)? as i32; + let data = self.read_instruction_long(bus)? as i32; Ok(Instruction::LINK(get_low_reg(ins), data)) }, (0b000, _) => { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; + let target = self.decode_lower_effective_address(bus, ins, Some(Size::Byte))?; Ok(Instruction::NBCD(target)) }, (0b001, 0b000) => { @@ -289,7 +289,7 @@ impl M68kDecoder { Ok(Instruction::BKPT(get_low_reg(ins))) }, (0b001, _) => { - let target = self.decode_lower_effective_address(memory, ins, None)?; + let target = self.decode_lower_effective_address(bus, ins, None)?; Ok(Instruction::PEA(target)) }, (0b010, 0b000) => { @@ -307,7 +307,7 @@ impl M68kDecoder { if (ins & 0x0FF) == 0xFC { Ok(Instruction::ILLEGAL) } else { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + let target = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; match get_size(ins) { Some(size) => Ok(Instruction::TST(target, size)), None => Ok(Instruction::TAS(target)), @@ -315,7 +315,7 @@ impl M68kDecoder { } } else if ins_0f00 == 0xE00 { if (ins & 0x80) == 0x80 { - let target = self.decode_lower_effective_address(memory, ins, None)?; + let target = self.decode_lower_effective_address(bus, ins, None)?; if (ins & 0b01000000) == 0 { Ok(Instruction::JSR(target)) } else { @@ -326,7 +326,7 @@ impl M68kDecoder { } else if ins_00f0 == 0x50 { let reg = get_low_reg(ins); if (ins & 0b1000) == 0 { - let data = (self.read_instruction_word(memory)? as i16) as i32; + let data = (self.read_instruction_word(bus)? as i16) as i32; Ok(Instruction::LINK(reg, data)) } else { Ok(Instruction::UNLK(reg)) @@ -340,12 +340,12 @@ impl M68kDecoder { 0x70 => Ok(Instruction::RESET), 0x71 => Ok(Instruction::NOP), 0x72 => { - let data = self.read_instruction_word(memory)?; + let data = self.read_instruction_word(bus)?; Ok(Instruction::STOP(data)) }, 0x73 => Ok(Instruction::RTE), 0x74 if self.cputype >= M68kType::MC68010 => { - let offset = self.read_instruction_word(memory)? as i16; + let offset = self.read_instruction_word(bus)? as i16; Ok(Instruction::RTD(offset)) }, 0x75 => Ok(Instruction::RTS), @@ -353,7 +353,7 @@ impl M68kDecoder { 0x77 => Ok(Instruction::RTR), 0x7A | 0x7B if self.cputype >= M68kType::MC68010 => { let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget }; - let ins2 = self.read_instruction_word(memory)?; + let ins2 = self.read_instruction_word(bus)?; let target = match ins2 & 0x8000 { 0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8), _ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8), @@ -373,10 +373,10 @@ impl M68kDecoder { } #[inline] - fn decode_group_addq_subq(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_addq_subq(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { match get_size(ins) { Some(size) => { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let mut data = ((ins & 0x0E00) >> 9) as u32; if data == 0 { data = 8; @@ -400,10 +400,10 @@ impl M68kDecoder { if mode == 0b001 { let reg = get_low_reg(ins); - let disp = self.read_instruction_word(memory)? as i16; + let disp = self.read_instruction_word(bus)? as i16; Ok(Instruction::DBcc(condition, reg, disp)) } else { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; + let target = self.decode_lower_effective_address(bus, ins, Some(Size::Byte))?; Ok(Instruction::Scc(condition, target)) } }, @@ -411,12 +411,12 @@ impl M68kDecoder { } #[inline] - fn decode_group_branch(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_branch(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { let mut disp = ((ins & 0xFF) as i8) as i32; if disp == 0 { - disp = (self.read_instruction_word(memory)? as i16) as i32; + disp = (self.read_instruction_word(bus)? as i16) as i32; } else if disp == -1 && self.cputype >= M68kType::MC68020 { - disp = self.read_instruction_long(memory)? as i32; + disp = self.read_instruction_long(bus)? as i32; } let condition = get_condition(ins); match condition { @@ -427,7 +427,7 @@ impl M68kDecoder { } #[inline] - fn decode_group_moveq(&mut self, _memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_moveq(&mut self, _bus: &mut M68kBusPort, ins: u16) -> Result { if (ins & 0x0100) != 0 { return Err(M68kError::Exception(Exceptions::IllegalInstruction)); } @@ -437,7 +437,7 @@ impl M68kDecoder { } #[inline] - fn decode_group_div_or(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_div_or(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { let size = get_size(ins); if (ins & 0x1F0) == 0x100 { @@ -450,18 +450,18 @@ impl M68kDecoder { } } else if let Some(size) = size { let data_reg = Target::DirectDReg(get_high_reg(ins)); - let effective_addr = self.decode_lower_effective_address(memory, ins, Some(size))?; + let effective_addr = self.decode_lower_effective_address(bus, ins, Some(size))?; let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) }; Ok(Instruction::OR(from, to, size)) } else { let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed }; - let effective_addr = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + let effective_addr = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; Ok(Instruction::DIVW(effective_addr, get_high_reg(ins), sign)) } } #[inline] - fn decode_group_sub(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_sub(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { let reg = get_high_reg(ins); let dir = (ins & 0x0100) >> 8; let size = get_size(ins); @@ -475,7 +475,7 @@ impl M68kDecoder { false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), } } else { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; if dir == 0 { Ok(Instruction::SUB(target, Target::DirectDReg(reg), size)) } else { @@ -485,14 +485,14 @@ impl M68kDecoder { }, None => { let size = if dir == 0 { Size::Word } else { Size::Long }; - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; Ok(Instruction::SUBA(target, reg, size)) }, } } #[inline] - fn decode_group_cmp_eor(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_cmp_eor(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { let reg = get_high_reg(ins); let optype = (ins & 0x0100) >> 8; let size = get_size(ins); @@ -501,17 +501,17 @@ impl M68kDecoder { if get_low_mode(ins) == 0b001 { Ok(Instruction::CMP(Target::IndirectARegInc(get_low_reg(ins)), Target::IndirectARegInc(reg), size)) } else { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; Ok(Instruction::EOR(Target::DirectDReg(reg), target, size)) } }, (0b0, Some(size)) => { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; Ok(Instruction::CMP(target, Target::DirectDReg(reg), size)) }, (_, None) => { let size = if optype == 0 { Size::Word } else { Size::Long }; - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; Ok(Instruction::CMPA(target, reg, size)) }, _ => Err(M68kError::Exception(Exceptions::IllegalInstruction)), @@ -519,7 +519,7 @@ impl M68kDecoder { } #[inline] - fn decode_group_mul_and(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_mul_and(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { let size = get_size(ins); if (ins & 0b0001_1111_0000) == 0b0001_0000_0000 { @@ -541,18 +541,18 @@ impl M68kDecoder { } } else if let Some(size) = size { let data_reg = Target::DirectDReg(get_high_reg(ins)); - let effective_addr = self.decode_lower_effective_address(memory, ins, Some(size))?; + let effective_addr = self.decode_lower_effective_address(bus, ins, Some(size))?; let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) }; Ok(Instruction::AND(from, to, size)) } else { let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed }; - let effective_addr = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + let effective_addr = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; Ok(Instruction::MULW(effective_addr, get_high_reg(ins), sign)) } } #[inline] - fn decode_group_add(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_add(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { let reg = get_high_reg(ins); let dir = (ins & 0x0100) >> 8; let size = get_size(ins); @@ -566,7 +566,7 @@ impl M68kDecoder { false => Ok(Instruction::ADDX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), } } else { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; if dir == 0 { Ok(Instruction::ADD(target, Target::DirectDReg(reg), size)) } else { @@ -576,13 +576,13 @@ impl M68kDecoder { }, None => { let size = if dir == 0 { Size::Word } else { Size::Long }; - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let target = self.decode_lower_effective_address(bus, ins, Some(size))?; Ok(Instruction::ADDA(target, reg, size)) }, } } - fn decode_group_shift(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result { + fn decode_group_shift(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result { match get_size(ins) { Some(size) => { let target = Target::DirectDReg(get_low_reg(ins)); @@ -613,7 +613,7 @@ impl M68kDecoder { }, None => { if (ins & 0x800) == 0 { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + let target = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; let count = Target::Immediate(1); let size = Size::Word; @@ -636,7 +636,7 @@ impl M68kDecoder { } } else if self.cputype > M68kType::MC68020 { // Bitfield instructions (MC68020+) - let ext = self.read_instruction_word(memory)?; + let ext = self.read_instruction_word(bus)?; let reg = ((ext & 0x7000) >> 12) as u8; let offset = match (ext & 0x0800) == 0 { @@ -649,7 +649,7 @@ impl M68kDecoder { false => RegOrImmediate::DReg((ext & 0x0007) as u8), }; - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + let target = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; match (ins & 0x0700) >> 8 { 0b010 => Ok(Instruction::BFCHG(target, offset, width)), 0b100 => Ok(Instruction::BFCLR(target, offset, width)), @@ -668,42 +668,42 @@ impl M68kDecoder { } } - fn read_instruction_word(&mut self, memory: &mut M68kBusPort) -> Result { - let word = memory.read_instruction_word(self.is_supervisor, self.end)?; + fn read_instruction_word(&mut self, bus: &mut M68kBusPort) -> Result { + let word = bus.read_instruction_word(self.is_supervisor, self.end)?; self.end += 2; Ok(word) } - fn read_instruction_long(&mut self, memory: &mut M68kBusPort) -> Result { - let word = memory.read_instruction_long(self.is_supervisor, self.end)?; + fn read_instruction_long(&mut self, bus: &mut M68kBusPort) -> Result { + let word = bus.read_instruction_long(self.is_supervisor, self.end)?; self.end += 4; Ok(word) } - fn decode_lower_effective_address(&mut self, memory: &mut M68kBusPort, ins: u16, size: Option) -> Result { + fn decode_lower_effective_address(&mut self, bus: &mut M68kBusPort, ins: u16, size: Option) -> Result { let reg = get_low_reg(ins); let mode = get_low_mode(ins); - self.get_mode_as_target(memory, mode, reg, size) + self.get_mode_as_target(bus, mode, reg, size) } - fn decode_upper_effective_address(&mut self, memory: &mut M68kBusPort, ins: u16, size: Option) -> Result { + fn decode_upper_effective_address(&mut self, bus: &mut M68kBusPort, ins: u16, size: Option) -> Result { let reg = get_high_reg(ins); let mode = get_high_mode(ins); - self.get_mode_as_target(memory, mode, reg, size) + self.get_mode_as_target(bus, mode, reg, size) } - fn get_extension_displacement(&mut self, memory: &mut M68kBusPort, select: u16) -> Result { + fn get_extension_displacement(&mut self, bus: &mut M68kBusPort, select: u16) -> Result { let result = match select { 0b00 | 0b01 => 0, - 0b10 => sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word), - 0b11 => self.read_instruction_long(memory)? as i32, + 0b10 => sign_extend_to_long(self.read_instruction_word(bus)? as u32, Size::Word), + 0b11 => self.read_instruction_long(bus)? as i32, _ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)), }; Ok(result) } - fn decode_extension_word(&mut self, memory: &mut M68kBusPort, areg: Option) -> Result { - let brief_extension = self.read_instruction_word(memory)?; + fn decode_extension_word(&mut self, bus: &mut M68kBusPort, areg: Option) -> Result { + let brief_extension = self.read_instruction_word(bus)?; let use_brief = (brief_extension & 0x0100) == 0; @@ -744,8 +744,8 @@ impl M68kDecoder { (true, Some(areg)) => BaseRegister::AReg(areg), }; let opt_index_reg = if use_index { Some(index_reg) } else { None }; - let base_disp = self.get_extension_displacement(memory, (brief_extension & 0x0030) >> 4)?; - let outer_disp = self.get_extension_displacement(memory, brief_extension & 0x0003)?; + let base_disp = self.get_extension_displacement(bus, (brief_extension & 0x0030) >> 4)?; + let outer_disp = self.get_extension_displacement(bus, brief_extension & 0x0003)?; match (use_sub_indirect, pre_not_post) { (false, _) => Ok(Target::IndirectRegOffset(opt_base_reg, opt_index_reg, base_disp)), @@ -755,7 +755,7 @@ impl M68kDecoder { } } - pub(super) fn get_mode_as_target(&mut self, memory: &mut M68kBusPort, mode: u8, reg: u8, size: Option) -> Result { + pub(super) fn get_mode_as_target(&mut self, bus: &mut M68kBusPort, mode: u8, reg: u8, size: Option) -> Result { let value = match mode { 0b000 => Target::DirectDReg(reg), 0b001 => Target::DirectAReg(reg), @@ -763,33 +763,33 @@ impl M68kDecoder { 0b011 => Target::IndirectARegInc(reg), 0b100 => Target::IndirectARegDec(reg), 0b101 => { - let displacement = sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word); + let displacement = sign_extend_to_long(self.read_instruction_word(bus)? as u32, Size::Word); Target::IndirectRegOffset(BaseRegister::AReg(reg), None, displacement) }, 0b110 => { - self.decode_extension_word(memory, Some(reg))? + self.decode_extension_word(bus, Some(reg))? }, 0b111 => { match reg { 0b000 => { - let value = sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word) as u32; + let value = sign_extend_to_long(self.read_instruction_word(bus)? as u32, Size::Word) as u32; Target::IndirectMemory(value, Size::Word) }, 0b001 => { - let value = self.read_instruction_long(memory)?; + let value = self.read_instruction_long(bus)?; Target::IndirectMemory(value, Size::Long) }, 0b010 => { - let displacement = sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word); + let displacement = sign_extend_to_long(self.read_instruction_word(bus)? as u32, Size::Word); Target::IndirectRegOffset(BaseRegister::PC, None, displacement) }, 0b011 => { - self.decode_extension_word(memory, None)? + self.decode_extension_word(bus, None)? }, 0b100 => { let data = match size { - Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(memory)? as u32, - Some(Size::Long) => self.read_instruction_long(memory)?, + Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(bus)? as u32, + Some(Size::Long) => self.read_instruction_long(bus)?, None => return Err(M68kError::Exception(Exceptions::IllegalInstruction)), }; Target::Immediate(data) @@ -802,19 +802,19 @@ impl M68kDecoder { Ok(value) } - pub fn dump_disassembly(&mut self, memory: &mut M68kBusPort, start: u32, length: u32) { + pub fn dump_disassembly(&mut self, bus: &mut M68kBusPort, start: u32, length: u32) { let mut next = start; while next < (start + length) { - match self.decode_at(memory, self.is_supervisor, next) { + match self.decode_at(bus, self.is_supervisor, next) { Ok(()) => { - self.dump_decoded(memory); + self.dump_decoded(bus); next = self.end; }, Err(err) => { println!("{:?}", err); match err { M68kError::Exception(ex) if ex == Exceptions::IllegalInstruction => { - println!(" at {:08x}: {:04x}", self.start, memory.port.read_beu16(memory.current_clock, self.start as Address).unwrap()); + println!(" at {:08x}: {:04x}", self.start, bus.port.read_beu16(bus.current_clock, self.start as Address).unwrap()); }, _ => { }, } @@ -824,10 +824,10 @@ impl M68kDecoder { } } - pub fn dump_decoded(&mut self, memory: &mut M68kBusPort) { + pub fn dump_decoded(&mut self, bus: &mut M68kBusPort) { let ins_data: Result = (0..((self.end - self.start) / 2)).map(|offset| - Ok(format!("{:04x} ", memory.port.read_beu16(memory.current_clock, (self.start + (offset * 2)) as Address).unwrap())) + Ok(format!("{:04x} ", bus.port.read_beu16(bus.current_clock, (self.start + (offset * 2)) as Address).unwrap())) ).collect(); println!("{:#010x}: {}\n\t{}\n", self.start, ins_data.unwrap(), self.instruction); } diff --git a/emulator/cpus/m68k/src/execute.rs b/emulator/cpus/m68k/src/execute.rs index 76d5db2..900eff9 100644 --- a/emulator/cpus/m68k/src/execute.rs +++ b/emulator/cpus/m68k/src/execute.rs @@ -3,9 +3,10 @@ use femtos::{Instant, Duration}; use moa_core::{System, Error, Address, Steppable, Interruptable, Addressable, Debuggable, Transmutable}; -use crate::state::{M68k, M68kType, M68kError, ClockCycles, Status, Flags, Exceptions, InterruptPriority}; -use crate::memory::{MemType, MemAccess}; +use crate::state::{M68k, M68kType, M68kError, M68kState, ClockCycles, Status, Flags, Exceptions, InterruptPriority}; +use crate::memory::{MemType, MemAccess, M68kBusPort}; use crate::decode::M68kDecoder; +use crate::debugger::M68kDebugger; use crate::timing::M68kInstructionTiming; use crate::instructions::{ Register, @@ -32,14 +33,89 @@ pub enum Used { Twice, } + +#[derive(Clone, Debug)] +pub struct M68kCycle { + pub decoder: M68kDecoder, + pub timing: M68kInstructionTiming, + pub current_clock: Instant, +} + +impl M68kCycle { + pub fn default(cputype: M68kType, data_width: u8) -> Self { + Self { + decoder: M68kDecoder::new(cputype, true, 0), + timing: M68kInstructionTiming::new(cputype, data_width), + current_clock: Instant::START, + } + } + + pub fn new(cpu: &mut M68k, clock: Instant) -> Self { + let is_supervisor = cpu.state.sr & (Flags:: Supervisor as u16) != 0; + let pc = cpu.state.pc; + let data_width = cpu.port.data_width(); + let cputype = cpu.cputype; + Self { + decoder: M68kDecoder::new(cputype, is_supervisor, pc), + timing: M68kInstructionTiming::new(cputype, data_width), + current_clock: clock, + } + } + + pub fn begin<'a>(mut self, cpu: &'a mut M68k) -> M68kCycleGuard<'a> { + // TODO this port init_cycle must be integrated into the cycle struct instead + cpu.port.init_cycle(self.current_clock); + + M68kCycleGuard { + state: &mut cpu.state, + port: &mut cpu.port, + debugger: &mut cpu.debugger, + cycle: self, + } + } +} + +pub struct M68kCycleGuard<'a> { + pub state: &'a mut M68kState, + pub port: &'a mut M68kBusPort, + pub debugger: &'a mut M68kDebugger, + pub cycle: M68kCycle, +} + +impl<'a> M68kCycleGuard<'a> { + pub fn dump_state(&mut self) { + println!("Status: {:?}", self.state.status); + println!("PC: {:#010x}", self.state.pc); + println!("SR: {:#06x}", self.state.sr); + for i in 0..7 { + println!("D{}: {:#010x} A{}: {:#010x}", i, self.state.d_reg[i as usize], i, self.state.a_reg[i as usize]); + } + println!("D7: {:#010x} USP: {:#010x}", self.state.d_reg[7], self.state.usp); + println!(" SSP: {:#010x}", self.state.ssp); + + println!("Current Instruction: {:#010x} {:?}", self.cycle.decoder.start, self.cycle.decoder.instruction); + println!(); + self.port.dump_memory(self.state.ssp, 0x40); + println!(); + } + + pub fn finalize(self) -> M68kCycle { + self.cycle + } +} + impl Steppable for M68k { fn step(&mut self, system: &System) -> Result { - let clocks = self.step_internal(system)?; + let mut cycle = M68kCycle::new(self, system.clock); + let mut execution = cycle.begin(self); + let clocks = execution.step(system)?; + self.cycle = execution.finalize(); Ok(self.frequency.period_duration() * clocks as u64) } fn on_error(&mut self, _system: &System) { - self.dump_state(); + // TODO the cycle data in dropped by this point + //self.dump_state(); } } @@ -82,9 +158,9 @@ impl From for M68kError { } } -impl M68k { - pub fn step_internal(&mut self, system: &System) -> Result { - self.init_cycle(system.clock); +impl<'a> M68kCycleGuard<'a> { + #[inline] + pub fn step(&mut self, system: &System) -> Result { match self.state.status { Status::Init => self.reset_cpu(), Status::Stopped => Err(M68kError::Halted), @@ -105,14 +181,7 @@ impl M68k { } } - pub fn init_cycle(&mut self, clock: Instant) { - self.current_clock = clock; - self.decoder = M68kDecoder::new(self.cputype, self.is_supervisor(), self.state.pc); - self.timing = M68kInstructionTiming::new(self.cputype, self.port.data_width()); - self.port.init_cycle(clock); - self.timing.reset(); - } - + #[inline] pub fn reset_cpu(&mut self) -> Result { self.state.ssp = self.get_address_sized(0, Size::Long)?; self.state.pc = self.get_address_sized(4, Size::Long)?; @@ -120,6 +189,7 @@ impl M68k { Ok(16) } + #[inline] pub fn cycle_one(&mut self, system: &System) -> Result { self.check_breakpoints()?; @@ -127,9 +197,10 @@ impl M68k { self.execute_current()?; self.check_pending_interrupts(system)?; - Ok(self.timing.calculate_clocks(false, 1)) + Ok(self.cycle.timing.calculate_clocks(false, 1)) } + #[inline] pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), M68kError> { self.state.pending_ipl = match system.get_interrupt_controller().check() { (true, priority) => InterruptPriority::from_u8(priority), @@ -174,9 +245,9 @@ impl M68k { Ok(()) } - pub fn setup_group0_exception(&mut self, number: u8) -> Result<(), M68kError> { + fn setup_group0_exception(&mut self, number: u8) -> Result<(), M68kError> { let sr = self.state.sr; - let ins_word = self.decoder.instruction_word; + let ins_word = self.cycle.decoder.instruction_word; let extra_code = self.port.request.get_type_code(); let fault_size = self.port.request.size.in_bytes(); let fault_address = self.port.request.address; @@ -186,7 +257,7 @@ impl M68k { self.set_flag(Flags::Tracing, false); let offset = (number as u16) << 2; - if self.cputype >= M68kType::MC68010 { + if self.cycle.decoder.cputype >= M68kType::MC68010 { self.push_word(offset)?; } @@ -203,7 +274,7 @@ impl M68k { Ok(()) } - pub fn setup_normal_exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError> { + fn setup_normal_exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError> { let sr = self.state.sr; self.port.request.i_n_bit = true; @@ -215,7 +286,7 @@ impl M68k { } let offset = (number as u16) << 2; - if self.cputype >= M68kType::MC68010 { + if self.cycle.decoder.cputype >= M68kType::MC68010 { self.push_word(offset)?; } self.push_long(self.state.pc)?; @@ -228,19 +299,21 @@ impl M68k { Ok(()) } + #[inline] pub fn decode_next(&mut self) -> Result<(), M68kError> { let is_supervisor = self.is_supervisor(); - self.decoder.decode_at(&mut self.port, is_supervisor, self.state.pc)?; + self.cycle.decoder.decode_at(&mut self.port, is_supervisor, self.state.pc)?; - self.timing.add_instruction(&self.decoder.instruction); + self.cycle.timing.add_instruction(&self.cycle.decoder.instruction); - self.state.pc = self.decoder.end; + self.state.pc = self.cycle.decoder.end; Ok(()) } + #[inline] pub fn execute_current(&mut self) -> Result<(), M68kError> { - match self.decoder.instruction { + match self.cycle.decoder.instruction { Instruction::ABCD(src, dest) => self.execute_abcd(src, dest), Instruction::ADD(src, dest, size) => self.execute_add(src, dest, size), Instruction::ADDA(src, dest, size) => self.execute_adda(src, dest, size), @@ -475,7 +548,7 @@ impl M68k { fn execute_bcc(&mut self, cond: Condition, offset: i32) -> Result<(), M68kError> { let should_branch = self.get_current_condition(cond); if should_branch { - if let Err(err) = self.set_pc(self.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { + if let Err(err) = self.set_pc(self.cycle.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { self.state.pc -= 2; return Err(err); } @@ -484,7 +557,7 @@ impl M68k { } fn execute_bra(&mut self, offset: i32) -> Result<(), M68kError> { - if let Err(err) = self.set_pc(self.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { + if let Err(err) = self.set_pc(self.cycle.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { self.state.pc -= 2; return Err(err); } @@ -495,7 +568,7 @@ impl M68k { self.push_long(self.state.pc)?; let sp = *self.get_stack_pointer_mut(); self.debugger.stack_tracer.push_return(sp); - if let Err(err) = self.set_pc(self.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { + if let Err(err) = self.set_pc(self.cycle.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { self.state.pc -= 2; return Err(err); } @@ -618,7 +691,7 @@ impl M68k { } fn execute_clr(&mut self, target: Target, size: Size) -> Result<(), M68kError> { - if self.cputype == M68kType::MC68000 { + if self.cycle.decoder.cputype == M68kType::MC68000 { self.get_target_value(target, size, Used::Twice)?; self.set_target_value(target, 0, size, Used::Twice)?; } else { @@ -653,7 +726,7 @@ impl M68k { let next = ((get_value_sized(self.state.d_reg[reg as usize], Size::Word) as u16) as i16).wrapping_sub(1); set_value_sized(&mut self.state.d_reg[reg as usize], next as u32, Size::Word); if next != -1 { - if let Err(err) = self.set_pc(self.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { + if let Err(err) = self.set_pc(self.cycle.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { self.state.pc -= 2; return Err(err); } @@ -912,7 +985,7 @@ impl M68k { let addr = self.get_target_address(target)?; // If we're using a MC68020 or higher, and it was Post-Inc/Pre-Dec target, then update the value before it's stored - if self.cputype >= M68kType::MC68020 { + if self.cycle.decoder.cputype >= M68kType::MC68020 { match target { Target::IndirectARegInc(reg) | Target::IndirectARegDec(reg) => { let a_reg_mut = self.get_a_reg_mut(reg); @@ -1217,7 +1290,7 @@ impl M68k { let sr = self.pop_word()?; let addr = self.pop_long()?; - if self.cputype >= M68kType::MC68010 { + if self.cycle.decoder.cputype >= M68kType::MC68010 { let _ = self.pop_word()?; } @@ -1545,14 +1618,14 @@ impl M68k { *self.get_stack_pointer_mut() -= 2; let addr = *self.get_stack_pointer_mut(); self.port.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Write, MemType::Data, false)?; - self.port.port.write_beu16(self.current_clock, addr as Address, value)?; + self.port.port.write_beu16(self.cycle.current_clock, addr as Address, value)?; Ok(()) } fn pop_word(&mut self) -> Result { let addr = *self.get_stack_pointer_mut(); self.port.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Read, MemType::Data, false)?; - let value = self.port.port.read_beu16(self.current_clock, addr as Address)?; + let value = self.port.port.read_beu16(self.cycle.current_clock, addr as Address)?; *self.get_stack_pointer_mut() += 2; Ok(value) } @@ -1561,14 +1634,14 @@ impl M68k { *self.get_stack_pointer_mut() -= 4; let addr = *self.get_stack_pointer_mut(); self.port.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Write, MemType::Data, false)?; - self.port.port.write_beu32(self.current_clock, addr as Address, value)?; + self.port.port.write_beu32(self.cycle.current_clock, addr as Address, value)?; Ok(()) } fn pop_long(&mut self) -> Result { let addr = *self.get_stack_pointer_mut(); self.port.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Read, MemType::Data, false)?; - let value = self.port.port.read_beu32(self.current_clock, addr as Address)?; + let value = self.port.port.read_beu32(self.cycle.current_clock, addr as Address)?; *self.get_stack_pointer_mut() += 4; Ok(value) } @@ -1605,7 +1678,7 @@ impl M68k { fn get_base_reg_value(&self, base_reg: BaseRegister) -> u32 { match base_reg { BaseRegister::None => 0, - BaseRegister::PC => self.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(reg) => self.state.a_reg[reg as usize], } @@ -1659,7 +1732,7 @@ impl M68k { } fn set_sr(&mut self, value: u16) { - let mask = if self.cputype <= M68kType::MC68010 { 0xA71F } else { 0xF71F }; + let mask = if self.cycle.decoder.cputype <= M68kType::MC68010 { 0xA71F } else { 0xF71F }; self.state.sr = value & mask; } diff --git a/emulator/cpus/m68k/src/memory.rs b/emulator/cpus/m68k/src/memory.rs index c4eff72..71c0d4c 100644 --- a/emulator/cpus/m68k/src/memory.rs +++ b/emulator/cpus/m68k/src/memory.rs @@ -1,5 +1,6 @@ use femtos::Instant; +use emulator_hal::bus::{BusType, BusAccess}; use moa_core::{Error, Address, Addressable, BusPort}; @@ -187,7 +188,22 @@ fn validate_address(addr: u32) -> Result { } } +/* +impl BusType for M68kBusPort { + type Instant = Instant; + type Error = Error; +} +impl BusAccess for M68kBusPort { + fn read(&mut self, now: Self::Instant, addr: Address, data: &mut [u8]) -> Result { + self. + } + + fn write(&mut self, now: Self::Instant, addr: Address, data: &[u8]) -> Result { + + } +} +*/ /* pub(crate) struct TargetAccess { diff --git a/emulator/cpus/m68k/src/state.rs b/emulator/cpus/m68k/src/state.rs index fc6dcdf..745f61c 100644 --- a/emulator/cpus/m68k/src/state.rs +++ b/emulator/cpus/m68k/src/state.rs @@ -10,6 +10,7 @@ use crate::debugger::M68kDebugger; use crate::memory::M68kBusPort; use crate::timing::M68kInstructionTiming; use crate::instructions::Target; +use crate::execute::M68kCycle; pub type ClockCycles = u16; @@ -113,11 +114,12 @@ pub struct M68k { pub cputype: M68kType, pub frequency: Frequency, pub state: M68kState, - pub decoder: M68kDecoder, - pub timing: M68kInstructionTiming, + //pub decoder: M68kDecoder, + //pub timing: M68kInstructionTiming, pub debugger: M68kDebugger, pub port: M68kBusPort, - pub current_clock: Instant, + //pub current_clock: Instant, + pub cycle: M68kCycle, } impl Default for M68kState { @@ -141,15 +143,17 @@ impl Default for M68kState { impl M68k { pub fn new(cputype: M68kType, frequency: Frequency, port: BusPort) -> M68k { + let data_width = port.data_width(); M68k { cputype, frequency, state: M68kState::default(), - decoder: M68kDecoder::new(cputype, true, 0), - timing: M68kInstructionTiming::new(cputype, port.data_width()), + //decoder: M68kDecoder::new(cputype, true, 0), + //timing: M68kInstructionTiming::new(cputype, port.data_width()), debugger: M68kDebugger::default(), port: M68kBusPort::new(port), - current_clock: Instant::START, + //current_clock: Instant::START, + cycle: M68kCycle::default(cputype, data_width), } } @@ -162,21 +166,6 @@ impl M68k { } } - pub fn dump_state(&mut self) { - println!("Status: {:?}", self.state.status); - println!("PC: {:#010x}", self.state.pc); - println!("SR: {:#06x}", self.state.sr); - for i in 0..7 { - println!("D{}: {:#010x} A{}: {:#010x}", i, self.state.d_reg[i as usize], i, self.state.a_reg[i as usize]); - } - println!("D7: {:#010x} USP: {:#010x}", self.state.d_reg[7], self.state.usp); - println!(" SSP: {:#010x}", self.state.ssp); - - println!("Current Instruction: {:#010x} {:?}", self.decoder.start, self.decoder.instruction); - println!(); - self.port.dump_memory(self.state.ssp, 0x40); - println!(); - } } impl InterruptPriority { diff --git a/emulator/cpus/m68k/src/tests.rs b/emulator/cpus/m68k/src/tests.rs index d694287..e60c7fd 100644 --- a/emulator/cpus/m68k/src/tests.rs +++ b/emulator/cpus/m68k/src/tests.rs @@ -255,13 +255,16 @@ mod execute_unit_tests { use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Steppable, Device}; use crate::{M68k, M68kType}; - use crate::execute::Used; + use crate::execute::{Used, M68kCycle, M68kCycleGuard}; use crate::instructions::{Instruction, Target, Size}; const INIT_STACK: Address = 0x00002000; const INIT_ADDR: Address = 0x00000010; - fn init_execute_test(cputype: M68kType) -> (M68k, System) { + fn run_execute_test(cputype: M68kType, mut test_func: F) + where + F: FnMut(M68kCycleGuard), + { let mut system = System::default(); // Insert basic initialization @@ -273,11 +276,14 @@ mod execute_unit_tests { let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10), system.bus.clone(), 0); cpu.step(&system).unwrap(); - cpu.decoder.init(true, cpu.state.pc); - assert_eq!(cpu.state.pc, INIT_ADDR as u32); - assert_eq!(cpu.state.ssp, INIT_STACK as u32); - assert_eq!(cpu.decoder.instruction, Instruction::NOP); - (cpu, system) + let mut cycle = M68kCycle::new(&mut cpu, system.clock); + let mut execution = cycle.begin(&mut cpu); + execution.cycle.decoder.init(true, execution.state.pc); + assert_eq!(execution.state.pc, INIT_ADDR as u32); + assert_eq!(execution.state.ssp, INIT_STACK as u32); + assert_eq!(execution.cycle.decoder.instruction, Instruction::NOP); + + test_func(execution); } // @@ -286,86 +292,86 @@ mod execute_unit_tests { #[test] fn target_value_direct_d() { - let (mut cpu, _) = init_execute_test(M68kType::MC68010); + run_execute_test(M68kType::MC68010, |mut cycle| { + let size = Size::Word; + let expected = 0x1234; + let target = Target::DirectDReg(1); - let size = Size::Word; - let expected = 0x1234; - let target = Target::DirectDReg(1); - - cpu.state.d_reg[1] = expected; - let result = cpu.get_target_value(target, size, Used::Once).unwrap(); - assert_eq!(result, expected); + cycle.state.d_reg[1] = expected; + let result = cycle.get_target_value(target, size, Used::Once).unwrap(); + assert_eq!(result, expected); + }); } #[test] fn target_value_direct_a() { - let (mut cpu, _) = init_execute_test(M68kType::MC68010); + run_execute_test(M68kType::MC68010, |mut cycle| { + let size = Size::Word; + let expected = 0x1234; + let target = Target::DirectAReg(2); - let size = Size::Word; - let expected = 0x1234; - let target = Target::DirectAReg(2); - - cpu.state.a_reg[2] = expected; - let result = cpu.get_target_value(target, size, Used::Once).unwrap(); - assert_eq!(result, expected); + cycle.state.a_reg[2] = expected; + let result = cycle.get_target_value(target, size, Used::Once).unwrap(); + assert_eq!(result, expected); + }); } #[test] fn target_value_indirect_a() { - let (mut cpu, _) = init_execute_test(M68kType::MC68010); + run_execute_test(M68kType::MC68010, |mut cycle| { + let size = Size::Long; + let expected = 0x12345678; + let target = Target::IndirectAReg(2); + cycle.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap(); - let size = Size::Long; - let expected = 0x12345678; - let target = Target::IndirectAReg(2); - cpu.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap(); - - cpu.state.a_reg[2] = INIT_ADDR as u32; - let result = cpu.get_target_value(target, size, Used::Once).unwrap(); - assert_eq!(result, expected); + cycle.state.a_reg[2] = INIT_ADDR as u32; + let result = cycle.get_target_value(target, size, Used::Once).unwrap(); + assert_eq!(result, expected); + }); } #[test] fn target_value_indirect_a_inc() { - let (mut cpu, _) = init_execute_test(M68kType::MC68010); + run_execute_test(M68kType::MC68010, |mut cycle| { + let size = Size::Long; + let expected = 0x12345678; + let target = Target::IndirectARegInc(2); + cycle.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap(); - let size = Size::Long; - let expected = 0x12345678; - let target = Target::IndirectARegInc(2); - cpu.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap(); - - cpu.state.a_reg[2] = INIT_ADDR as u32; - let result = cpu.get_target_value(target, size, Used::Once).unwrap(); - assert_eq!(result, expected); - assert_eq!(cpu.state.a_reg[2], (INIT_ADDR as u32) + 4); + cycle.state.a_reg[2] = INIT_ADDR as u32; + let result = cycle.get_target_value(target, size, Used::Once).unwrap(); + assert_eq!(result, expected); + assert_eq!(cycle.state.a_reg[2], (INIT_ADDR as u32) + 4); + }); } #[test] fn target_value_indirect_a_dec() { - let (mut cpu, _) = init_execute_test(M68kType::MC68010); + run_execute_test(M68kType::MC68010, |mut cycle| { + let size = Size::Long; + let expected = 0x12345678; + let target = Target::IndirectARegDec(2); + cycle.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap(); - let size = Size::Long; - let expected = 0x12345678; - let target = Target::IndirectARegDec(2); - cpu.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap(); - - cpu.state.a_reg[2] = (INIT_ADDR as u32) + 4; - let result = cpu.get_target_value(target, size, Used::Once).unwrap(); - assert_eq!(result, expected); - assert_eq!(cpu.state.a_reg[2], INIT_ADDR as u32); + cycle.state.a_reg[2] = (INIT_ADDR as u32) + 4; + let result = cycle.get_target_value(target, size, Used::Once).unwrap(); + assert_eq!(result, expected); + assert_eq!(cycle.state.a_reg[2], INIT_ADDR as u32); + }); } #[test] fn target_value_immediate() { - let (mut cpu, _) = init_execute_test(M68kType::MC68010); + run_execute_test(M68kType::MC68010, |mut cycle| { + let size = Size::Word; + let expected = 0x1234; - let size = Size::Word; - let expected = 0x1234; + let target = Target::Immediate(expected); - let target = Target::Immediate(expected); - - let result = cpu.get_target_value(target, size, Used::Once).unwrap(); - assert_eq!(result, expected); + let result = cycle.get_target_value(target, size, Used::Once).unwrap(); + assert_eq!(result, expected); + }); } } diff --git a/emulator/cpus/m68k/tests/decode_tests.rs b/emulator/cpus/m68k/tests/decode_tests.rs index de1c417..61a4f69 100644 --- a/emulator/cpus/m68k/tests/decode_tests.rs +++ b/emulator/cpus/m68k/tests/decode_tests.rs @@ -6,6 +6,7 @@ use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Device}; use moa_m68k::{M68k, M68kType}; use moa_m68k::instructions::{Instruction, Target, Size, Sign, XRegister, BaseRegister, IndexRegister, Direction}; use moa_m68k::assembler::M68kAssembler; +use moa_m68k::execute::M68kCycle; const INIT_STACK: Address = 0x00002000; const INIT_ADDR: Address = 0x00000010; @@ -63,7 +64,7 @@ const DECODE_TESTS: &'static [TestCase] = &[ ]; -fn init_decode_test(cputype: M68kType) -> (M68k, System) { +fn init_decode_test(cputype: M68kType) -> (M68k, M68kCycle, System) { let mut system = System::default(); // Insert basic initialization @@ -75,14 +76,14 @@ fn init_decode_test(cputype: M68kType) -> (M68k, System) { // Initialize the CPU and make sure it's in the expected state let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10), system.bus.clone(), 0); - cpu.reset_cpu().unwrap(); + //cpu.reset_cpu().unwrap(); assert_eq!(cpu.state.pc, INIT_ADDR as u32); assert_eq!(cpu.state.ssp, INIT_STACK as u32); - cpu.decoder.init(true, INIT_ADDR as u32); - assert_eq!(cpu.decoder.start, INIT_ADDR as u32); - assert_eq!(cpu.decoder.instruction, Instruction::NOP); - (cpu, system) + let cycle = M68kCycle::new(cpu, system.clock); + assert_eq!(cycle.decoder.start, INIT_ADDR as u32); + assert_eq!(cycle.decoder.instruction, Instruction::NOP); + (cpu, cycle, system) } fn load_memory(system: &System, data: &[u16]) { @@ -94,15 +95,17 @@ fn load_memory(system: &System, data: &[u16]) { } fn run_decode_test(case: &TestCase) { - let (mut cpu, system) = init_decode_test(case.cpu); + let (mut cpu, mut cycle, system) = init_decode_test(case.cpu); load_memory(&system, case.data); match &case.ins { Some(ins) => { - cpu.decode_next().unwrap(); + let mut execution = cycle.begin(cpu); + execution.decode_next().unwrap(); assert_eq!(cpu.decoder.instruction, ins.clone()); }, None => { - let next = cpu.decode_next(); + let mut execution = cycle.begin(cpu); + let next = execution.decode_next(); println!("{:?}", cpu.decoder.instruction); assert!(next.is_err()); }, diff --git a/emulator/cpus/m68k/tests/execute_tests.rs b/emulator/cpus/m68k/tests/execute_tests.rs index cbe4a69..27fe112 100644 --- a/emulator/cpus/m68k/tests/execute_tests.rs +++ b/emulator/cpus/m68k/tests/execute_tests.rs @@ -5,6 +5,7 @@ use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Steppable, De use moa_m68k::{M68k, M68kType}; use moa_m68k::state::M68kState; +use moa_m68k::execute::M68kCycle; use moa_m68k::instructions::{Instruction, Target, Size, Sign, Direction, Condition}; const INIT_STACK: Address = 0x00002000; @@ -34,7 +35,10 @@ struct TestCase { } -fn init_execute_test(cputype: M68kType) -> (M68k, System) { +fn run_execute_test(cputype: M68kType, mut test_func: F) +where + F: FnMut(M68kCycle, System), +{ let mut system = System::default(); // Insert basic initialization @@ -46,11 +50,13 @@ fn init_execute_test(cputype: M68kType) -> (M68k, System) { let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10), system.bus.clone(), 0); cpu.step(&system).unwrap(); - cpu.decoder.init(true, cpu.state.pc); - assert_eq!(cpu.state.pc, INIT_ADDR as u32); - assert_eq!(cpu.state.ssp, INIT_STACK as u32); - assert_eq!(cpu.decoder.instruction, Instruction::NOP); - (cpu, system) + + let cycle = M68kCycle::new(cpu); + assert_eq!(cycle.state.pc, INIT_ADDR as u32); + assert_eq!(cycle.state.ssp, INIT_STACK as u32); + assert_eq!(cycle.decoder.instruction, Instruction::NOP); + + test_func(cycle, system) } fn build_state(state: &TestState) -> M68kState { @@ -73,23 +79,23 @@ fn load_memory(system: &System, data: &[u16]) { } fn run_test(case: &TestCase) { - let (mut cpu, system) = init_execute_test(case.cputype); + run_execute_test(case.cputype, |mut cycle, system| { + let init_state = build_state(&case.init); + let expected_state = build_state(&case.fini); + system.get_bus().write_beu32(system.clock, MEM_ADDR as Address, case.init.mem).unwrap(); - let init_state = build_state(&case.init); - let expected_state = build_state(&case.fini); - system.get_bus().write_beu32(system.clock, MEM_ADDR as Address, case.init.mem).unwrap(); + load_memory(&system, case.data); + *cycle.state = init_state; - load_memory(&system, case.data); - cpu.state = init_state; + cycle.decode_next().unwrap(); + assert_eq!(cycle.decoder.instruction, case.ins); - cpu.decode_next().unwrap(); - assert_eq!(cpu.decoder.instruction, case.ins); + cycle.execute_current().unwrap(); + assert_eq!(*cycle.state, expected_state); - cpu.execute_current().unwrap(); - assert_eq!(cpu.state, expected_state); - - let mem = system.get_bus().read_beu32(system.clock, MEM_ADDR as Address).unwrap(); - assert_eq!(mem, case.fini.mem); + let mem = system.get_bus().read_beu32(system.clock, MEM_ADDR as Address).unwrap(); + assert_eq!(mem, case.fini.mem); + }); } #[test] diff --git a/emulator/cpus/z80/Cargo.toml b/emulator/cpus/z80/Cargo.toml index 0a28c66..0478736 100644 --- a/emulator/cpus/z80/Cargo.toml +++ b/emulator/cpus/z80/Cargo.toml @@ -9,3 +9,4 @@ thiserror = "1.0" femtos = "0.1" moa-core = { path = "../../core" } moa-signals = { path = "../../libraries/signals" } +emulator-hal = { path = "/media/work/projects/emulator-hal/emulator-hal" } diff --git a/emulator/cpus/z80/src/debugger.rs b/emulator/cpus/z80/src/debugger.rs index 0c06779..99427fb 100644 --- a/emulator/cpus/z80/src/debugger.rs +++ b/emulator/cpus/z80/src/debugger.rs @@ -1,7 +1,7 @@ use moa_core::{System, Error, Address, Debuggable}; -use crate::state::Z80; +use crate::state::{Z80, Z80Error}; use crate::decode::Z80Decoder; use crate::instructions::Register; @@ -47,7 +47,7 @@ impl Debuggable for Z80 { } impl Z80 { - pub fn check_breakpoints(&mut self) -> Result<(), Error> { + pub fn check_breakpoints(&mut self) -> Result<(), Z80Error> { for breakpoint in &self.debugger.breakpoints { if *breakpoint == self.state.pc { if self.debugger.skip_breakpoint > 0 { @@ -55,7 +55,7 @@ impl Z80 { return Ok(()); } else { self.debugger.skip_breakpoint = 1; - return Err(Error::breakpoint(format!("breakpoint reached: {:08x}", *breakpoint))); + return Err(Z80Error::Breakpoint); } } } diff --git a/emulator/cpus/z80/src/decode.rs b/emulator/cpus/z80/src/decode.rs index 37fcd53..c394caa 100644 --- a/emulator/cpus/z80/src/decode.rs +++ b/emulator/cpus/z80/src/decode.rs @@ -6,6 +6,18 @@ use moa_core::{Address, Addressable}; use crate::state::Z80Error; use crate::instructions::{Direction, Condition, Register, RegisterPair, IndexRegister, IndexRegisterHalf, SpecialRegister, InterruptMode, Target, LoadTarget, UndocumentedCopy, Instruction}; +use emulator_hal::bus::{BusType, BusAccess}; + +struct Z80Bus; + +type Z80Address = (bool, u16); + +impl BusType for Z80Bus { + //type Address = (bool, u16); + type Error = Z80Error; + type Instant = Instant; +} + #[derive(Clone)] pub struct Z80Decoder { pub clock: Instant, @@ -27,6 +39,16 @@ impl Default for Z80Decoder { } } +/* + fn read_test(&mut self, device: &mut B) -> Result + where + B: BusAccess, + { + device.read_u8(self.clock, (false, self.end as u16)) + .map_err(|err| Z80Error::BusError(format!("butts"))) + } +*/ + impl Z80Decoder { pub fn decode_at(&mut self, memory: &mut dyn Addressable, clock: Instant, start: u16) -> Result<(), Z80Error> { self.clock = clock; @@ -525,7 +547,6 @@ impl Z80Decoder { } - fn read_instruction_byte(&mut self, device: &mut dyn Addressable) -> Result { let byte = device.read_u8(self.clock, self.end as Address)?; self.end = self.end.wrapping_add(1); diff --git a/emulator/cpus/z80/src/state.rs b/emulator/cpus/z80/src/state.rs index c19ce90..5a58db0 100644 --- a/emulator/cpus/z80/src/state.rs +++ b/emulator/cpus/z80/src/state.rs @@ -1,4 +1,5 @@ +use std::fmt; use std::rc::Rc; use std::cell::RefCell; use femtos::{Instant, Frequency}; @@ -93,7 +94,7 @@ impl Z80State { } #[derive(Clone, Debug, thiserror::Error)] -pub enum Z80Error { +pub enum Z80Error /* */ { #[error("cpu halted")] Halted, #[error("breakpoint reached")] @@ -101,7 +102,7 @@ pub enum Z80Error { #[error("unimplemented instruction {0:?}")] Unimplemented(Instruction), #[error("bus error: {0}")] - BusError(String), + BusError(String /* B */), } #[derive(Clone)] diff --git a/emulator/frontends/pixels/Cargo.lock b/emulator/frontends/pixels/Cargo.lock index 701e054..a05a06a 100644 --- a/emulator/frontends/pixels/Cargo.lock +++ b/emulator/frontends/pixels/Cargo.lock @@ -35,9 +35,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" +checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b" dependencies = [ "cfg-if", "once_cell", @@ -191,7 +191,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -286,9 +286,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3286b845d0fccbdd15af433f61c5970e711987036cb468f437ff6badd70f4e24" +checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" dependencies = [ "libc", ] @@ -328,7 +328,7 @@ checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", - "libloading 0.8.1", + "libloading 0.8.2", ] [[package]] @@ -499,7 +499,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.1", + "libloading 0.8.2", ] [[package]] @@ -514,6 +514,10 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "emulator-hal" +version = "0.1.0" + [[package]] name = "env_logger" version = "0.9.3" @@ -722,9 +726,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.3" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -827,12 +831,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.4", ] [[package]] @@ -858,9 +862,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "mach" @@ -936,9 +940,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -958,24 +962,38 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-host", ] [[package]] name = "moa-core" version = "0.1.0" dependencies = [ + "emulator-hal", "femtos", "log", + "moa-host", + "thiserror", +] + +[[package]] +name = "moa-host" +version = "0.1.0" +dependencies = [ + "femtos", + "thiserror", ] [[package]] name = "moa-m68k" version = "0.1.0" dependencies = [ + "emulator-hal", "femtos", "log", "moa-core", "moa-parsing", + "thiserror", ] [[package]] @@ -994,6 +1012,7 @@ dependencies = [ "log", "moa-audio", "moa-core", + "moa-host", ] [[package]] @@ -1008,6 +1027,7 @@ dependencies = [ "log", "moa-common", "moa-core", + "moa-host", "moa-systems-genesis", "pixels", "pollster", @@ -1018,6 +1038,13 @@ dependencies = [ "winit", ] +[[package]] +name = "moa-signals" +version = "0.1.0" +dependencies = [ + "femtos", +] + [[package]] name = "moa-systems-genesis" version = "0.1.0" @@ -1025,8 +1052,10 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-host", "moa-m68k", "moa-peripherals-yamaha", + "moa-signals", "moa-z80", ] @@ -1034,9 +1063,12 @@ dependencies = [ name = "moa-z80" version = "0.1.0" dependencies = [ + "emulator-hal", "femtos", "log", "moa-core", + "moa-signals", + "thiserror", ] [[package]] @@ -1217,7 +1249,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -1590,7 +1622,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -1749,9 +1781,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.50" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -1784,7 +1816,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -1824,7 +1856,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.3", + "indexmap 2.2.5", "toml_datetime", "winnow", ] @@ -1876,9 +1908,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -1911,7 +1943,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", "wasm-bindgen-shared", ] @@ -1945,7 +1977,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2256,6 +2288,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -2268,6 +2315,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + [[package]] name = "windows_aarch64_msvc" version = "0.37.0" @@ -2286,6 +2339,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + [[package]] name = "windows_i686_gnu" version = "0.37.0" @@ -2304,6 +2363,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + [[package]] name = "windows_i686_msvc" version = "0.37.0" @@ -2322,6 +2387,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + [[package]] name = "windows_x86_64_gnu" version = "0.37.0" @@ -2340,6 +2411,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -2352,6 +2429,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + [[package]] name = "windows_x86_64_msvc" version = "0.37.0" @@ -2370,6 +2453,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + [[package]] name = "winit" version = "0.28.7" @@ -2454,5 +2543,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] diff --git a/emulator/frontends/pixels/Cargo.toml b/emulator/frontends/pixels/Cargo.toml index 4157095..6385e50 100644 --- a/emulator/frontends/pixels/Cargo.toml +++ b/emulator/frontends/pixels/Cargo.toml @@ -18,7 +18,7 @@ moa-systems-genesis = { path = "../../systems/genesis" } [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1" console_log = "1.0" -wasm-bindgen = "0.2.91" +wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" web-sys = "0.3" wgpu = { version = "0.15", features = ["webgl"] } diff --git a/todo.txt b/todo.txt index 195d0f6..abc086e 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,16 @@ + +* the idea would be, instead of argument drilling, you create an object that is short lived, that lasts one instruction, or possibly even parts of one instruction, and + it has some references instead of "moving" data (or if you move, you move and move out without cloning), such that you can bundle everything up, call a method on the + bundle, with the execution context and state all part of or reference by the bundle, all instructions would be implemented on the bundle and not the state alone, and + after the instruction, or when transitioning from one phase to the next, you'd decompose the bundle back into its parts, and return before being called again to + repeat the process with the next instruction + + +* it doesn't work when using debug due to math checks, so fix them + + + * change all the inspection and debugging things to return a struct which can then be printed by the frontend * there are many issues with the coprocessor address space, and the VDP