mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-23 01:36:40 +00:00
Refactoring m68k to use a temporary cycle struct
I'm trying to extract the memory/bus interface, and pass it in at the start of each cycle instead of having the BusPort permanently embedded, which will allow migrating to emulator-hal. The functional way would be argument drilling; passing an extra argument to each function in the entire execution core. The problem is that it's messy, so a solution that is still functional is to implement all of the execution logic on a newtype that contains a reference to the mutable state and the owned cycle data, and at the end of the cycle, decompose the M68kCycleGuard that holds the reference, and keep the cycle data for debugging purposes.
This commit is contained in:
parent
83289d6b8e
commit
cff6a48cc7
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -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]]
|
||||
|
@ -13,6 +13,9 @@ exclude = [
|
||||
]
|
||||
default-members = ["emulator/frontends/minifb"]
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 3
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
#overflow-checks = true
|
||||
|
@ -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" }
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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<usize, Self::Error> {
|
||||
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<usize, Self::Error> {
|
||||
let addr = addr as usize;
|
||||
self.0[addr..addr + data.len()].copy_from_slice(data);
|
||||
Ok(data.len())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -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" }
|
||||
|
@ -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 {
|
||||
|
@ -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<Instruction, M68kError> {
|
||||
let ins = self.read_instruction_word(memory)?;
|
||||
pub fn decode_next(&mut self, bus: &mut M68kBusPort) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_bit_ops(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_misc(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_addq_subq(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_branch(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_moveq(&mut self, _bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_div_or(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_sub(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_cmp_eor(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_mul_and(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_add(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<Instruction, M68kError> {
|
||||
fn decode_group_shift(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
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<u16, M68kError> {
|
||||
let word = memory.read_instruction_word(self.is_supervisor, self.end)?;
|
||||
fn read_instruction_word(&mut self, bus: &mut M68kBusPort) -> Result<u16, M68kError> {
|
||||
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<u32, M68kError> {
|
||||
let word = memory.read_instruction_long(self.is_supervisor, self.end)?;
|
||||
fn read_instruction_long(&mut self, bus: &mut M68kBusPort) -> Result<u32, M68kError> {
|
||||
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<Size>) -> Result<Target, M68kError> {
|
||||
fn decode_lower_effective_address(&mut self, bus: &mut M68kBusPort, ins: u16, size: Option<Size>) -> Result<Target, M68kError> {
|
||||
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<Size>) -> Result<Target, M68kError> {
|
||||
fn decode_upper_effective_address(&mut self, bus: &mut M68kBusPort, ins: u16, size: Option<Size>) -> Result<Target, M68kError> {
|
||||
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<i32, M68kError> {
|
||||
fn get_extension_displacement(&mut self, bus: &mut M68kBusPort, select: u16) -> Result<i32, M68kError> {
|
||||
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<u8>) -> Result<Target, M68kError> {
|
||||
let brief_extension = self.read_instruction_word(memory)?;
|
||||
fn decode_extension_word(&mut self, bus: &mut M68kBusPort, areg: Option<u8>) -> Result<Target, M68kError> {
|
||||
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<Size>) -> Result<Target, M68kError> {
|
||||
pub(super) fn get_mode_as_target(&mut self, bus: &mut M68kBusPort, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, M68kError> {
|
||||
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<String, M68kError> =
|
||||
(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);
|
||||
}
|
||||
|
@ -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<Duration, Error> {
|
||||
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<Error> for M68kError {
|
||||
}
|
||||
}
|
||||
|
||||
impl M68k {
|
||||
pub fn step_internal(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
|
||||
self.init_cycle(system.clock);
|
||||
impl<'a> M68kCycleGuard<'a> {
|
||||
#[inline]
|
||||
pub fn step(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
|
||||
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<ClockCycles, M68kError> {
|
||||
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<ClockCycles, M68kError> {
|
||||
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<u16, M68kError> {
|
||||
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<u32, M68kError> {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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<u32, M68kError> {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl BusType for M68kBusPort {
|
||||
type Instant = Instant;
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl BusAccess<u32> for M68kBusPort {
|
||||
fn read(&mut self, now: Self::Instant, addr: Address, data: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
self.
|
||||
}
|
||||
|
||||
fn write(&mut self, now: Self::Instant, addr: Address, data: &[u8]) -> Result<usize, Self::Error> {
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
pub(crate) struct TargetAccess {
|
||||
|
@ -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 {
|
||||
|
@ -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<F>(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);
|
||||
|
||||
cpu.state.d_reg[1] = expected;
|
||||
let result = cpu.get_target_value(target, size, Used::Once).unwrap();
|
||||
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);
|
||||
|
||||
cpu.state.a_reg[2] = expected;
|
||||
let result = cpu.get_target_value(target, size, Used::Once).unwrap();
|
||||
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);
|
||||
cpu.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
|
||||
cycle.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();
|
||||
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);
|
||||
cpu.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
|
||||
cycle.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();
|
||||
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!(cpu.state.a_reg[2], (INIT_ADDR as u32) + 4);
|
||||
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);
|
||||
cpu.port.port.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
|
||||
cycle.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();
|
||||
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!(cpu.state.a_reg[2], INIT_ADDR as u32);
|
||||
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 target = Target::Immediate(expected);
|
||||
|
||||
let result = cpu.get_target_value(target, size, Used::Once).unwrap();
|
||||
let result = cycle.get_target_value(target, size, Used::Once).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
},
|
||||
|
@ -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<F>(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();
|
||||
|
||||
load_memory(&system, case.data);
|
||||
cpu.state = init_state;
|
||||
*cycle.state = init_state;
|
||||
|
||||
cpu.decode_next().unwrap();
|
||||
assert_eq!(cpu.decoder.instruction, case.ins);
|
||||
cycle.decode_next().unwrap();
|
||||
assert_eq!(cycle.decoder.instruction, case.ins);
|
||||
|
||||
cpu.execute_current().unwrap();
|
||||
assert_eq!(cpu.state, expected_state);
|
||||
cycle.execute_current().unwrap();
|
||||
assert_eq!(*cycle.state, expected_state);
|
||||
|
||||
let mem = system.get_bus().read_beu32(system.clock, MEM_ADDR as Address).unwrap();
|
||||
assert_eq!(mem, case.fini.mem);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -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" }
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<B>(&mut self, device: &mut B) -> Result<u8, Z80Error>
|
||||
where
|
||||
B: BusAccess<Z80Address, Instant = Instant>,
|
||||
{
|
||||
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<u8, Z80Error> {
|
||||
let byte = device.read_u8(self.clock, self.end as Address)?;
|
||||
self.end = self.end.wrapping_add(1);
|
||||
|
@ -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 /* <B: fmt::Display> */ {
|
||||
#[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)]
|
||||
|
143
emulator/frontends/pixels/Cargo.lock
generated
143
emulator/frontends/pixels/Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
@ -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"] }
|
||||
|
12
todo.txt
12
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
|
||||
|
Loading…
Reference in New Issue
Block a user