Refactored to separate out the BusPort, to eventually replace it

This commit is contained in:
transistor 2024-03-03 22:57:27 -08:00
parent 54ebcce94c
commit b4a35641e4
8 changed files with 426 additions and 278 deletions

View File

@ -3,7 +3,7 @@ use moa_core::{System, Error, Address, Addressable, Debuggable};
use super::state::M68k; use super::state::M68k;
use super::decode::M68kDecoder; use super::decode::M68kDecoder;
use super::execute::M68kCycleGuard; use super::execute::M68kCycleExecutor;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct StackTracer { pub struct StackTracer {
@ -49,8 +49,9 @@ impl Debuggable for M68k {
} }
fn print_disassembly(&mut self, addr: Address, count: usize) { fn print_disassembly(&mut self, addr: Address, count: usize) {
let mut decoder = M68kDecoder::new(self.cputype, true, 0); let mut decoder = M68kDecoder::new(self.info.chip, true, 0);
decoder.dump_disassembly(&mut self.port, addr as u32, count as u32); // TODO temporarily disabled
//decoder.dump_disassembly(&mut self.port, addr as u32, count as u32);
} }
fn run_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> { fn run_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {
@ -58,7 +59,7 @@ impl Debuggable for M68k {
"ds" | "stack" | "dumpstack" => { "ds" | "stack" | "dumpstack" => {
println!("Stack:"); println!("Stack:");
for addr in &self.debugger.stack_tracer.calls { for addr in &self.debugger.stack_tracer.calls {
println!(" {:08x}", self.port.port.read_beu32(system.clock, *addr as Address)?); println!(" {:08x}", self.port.read_beu32(system.clock, *addr as Address)?);
} }
}, },
"so" | "stepout" => { "so" | "stepout" => {
@ -70,7 +71,7 @@ impl Debuggable for M68k {
} }
} }
impl<'a> M68kCycleGuard<'a> { impl<'a> M68kCycleExecutor<'a> {
pub fn check_breakpoints(&mut self) -> Result<(), Error> { pub fn check_breakpoints(&mut self) -> Result<(), Error> {
for breakpoint in &self.debugger.breakpoints { for breakpoint in &self.debugger.breakpoints {
if *breakpoint == self.state.pc { if *breakpoint == self.state.pc {

View File

@ -1,5 +1,7 @@
use moa_core::{Address, Addressable}; use femtos::Instant;
use moa_core::{Address, Addressable, BusPort};
use crate::state::{M68kType, M68kError, Exceptions}; use crate::state::{M68kType, M68kError, Exceptions};
use crate::memory::M68kBusPort; use crate::memory::M68kBusPort;
@ -47,7 +49,14 @@ pub struct M68kDecoder {
pub instruction: Instruction, pub instruction: Instruction,
} }
pub struct InstructionDecoding<'a> {
port: &'a mut BusPort,
memory: &'a mut M68kBusPort,
decoder: &'a mut M68kDecoder,
}
impl M68kDecoder { impl M68kDecoder {
#[inline]
pub fn new(cputype: M68kType, is_supervisor: bool, start: u32) -> M68kDecoder { pub fn new(cputype: M68kType, is_supervisor: bool, start: u32) -> M68kDecoder {
M68kDecoder { M68kDecoder {
cputype, cputype,
@ -59,52 +68,91 @@ impl M68kDecoder {
} }
} }
#[inline(always)] #[inline]
pub fn init(&mut self, is_supervisor: bool, start: u32) { pub fn init(&mut self, is_supervisor: bool, start: u32) {
self.is_supervisor = is_supervisor; self.is_supervisor = is_supervisor;
self.start = start; self.start = start;
self.end = start; self.end = start;
} }
pub fn decode_at(&mut self, bus: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError> { #[inline]
pub fn decode_at(&mut self, port: &mut BusPort, memory: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError> {
self.init(is_supervisor, start); self.init(is_supervisor, start);
self.instruction = self.decode_next(bus)?; let mut decoding = InstructionDecoding {
port,
memory,
decoder: self,
};
self.instruction = decoding.decode_next()?;
Ok(()) Ok(())
} }
pub fn decode_next(&mut self, bus: &mut M68kBusPort) -> Result<Instruction, M68kError> { pub fn dump_disassembly(&mut self, port: &mut BusPort, memory: &mut M68kBusPort, start: u32, length: u32) {
let ins = self.read_instruction_word(bus)?; let mut next = start;
self.instruction_word = ins; while next < (start + length) {
match self.decode_at(port, memory, self.is_supervisor, next) {
Ok(()) => {
self.dump_decoded(memory.current_clock, port);
next = self.end;
},
Err(err) => {
println!("{:?}", err);
match err {
M68kError::Exception(ex) if ex == Exceptions::IllegalInstruction => {
println!(" at {:08x}: {:04x}", self.start, port.read_beu16(memory.current_clock, self.start as Address).unwrap());
},
_ => { },
}
return;
},
}
}
}
pub fn dump_decoded(&mut self, clock: Instant, port: &mut BusPort) {
let ins_data: Result<String, M68kError> =
(0..((self.end - self.start) / 2)).map(|offset|
Ok(format!("{:04x} ", port.read_beu16(clock, (self.start + (offset * 2)) as Address).unwrap()))
).collect();
println!("{:#010x}: {}\n\t{}\n", self.start, ins_data.unwrap(), self.instruction);
}
}
impl<'a> InstructionDecoding<'a> {
#[inline]
pub fn decode_next(&mut self) -> Result<Instruction, M68kError> {
let ins = self.read_instruction_word()?;
self.decoder.instruction_word = ins;
match ((ins & 0xF000) >> 12) as u8 { match ((ins & 0xF000) >> 12) as u8 {
OPCG_BIT_OPS => self.decode_group_bit_ops(bus, ins), OPCG_BIT_OPS => self.decode_group_bit_ops(ins),
OPCG_MOVE_BYTE => self.decode_group_move_byte(bus, ins), OPCG_MOVE_BYTE => self.decode_group_move_byte(ins),
OPCG_MOVE_LONG => self.decode_group_move_long(bus, ins), OPCG_MOVE_LONG => self.decode_group_move_long(ins),
OPCG_MOVE_WORD => self.decode_group_move_word(bus, ins), OPCG_MOVE_WORD => self.decode_group_move_word(ins),
OPCG_MISC => self.decode_group_misc(bus, ins), OPCG_MISC => self.decode_group_misc(ins),
OPCG_ADDQ_SUBQ => self.decode_group_addq_subq(bus, ins), OPCG_ADDQ_SUBQ => self.decode_group_addq_subq(ins),
OPCG_BRANCH => self.decode_group_branch(bus, ins), OPCG_BRANCH => self.decode_group_branch(ins),
OPCG_MOVEQ => self.decode_group_moveq(bus, ins), OPCG_MOVEQ => self.decode_group_moveq(ins),
OPCG_DIV_OR => self.decode_group_div_or(bus, ins), OPCG_DIV_OR => self.decode_group_div_or(ins),
OPCG_SUB => self.decode_group_sub(bus, ins), OPCG_SUB => self.decode_group_sub(ins),
OPCG_ALINE => Ok(Instruction::UnimplementedA(ins)), OPCG_ALINE => Ok(Instruction::UnimplementedA(ins)),
OPCG_CMP_EOR => self.decode_group_cmp_eor(bus, ins), OPCG_CMP_EOR => self.decode_group_cmp_eor(ins),
OPCG_MUL_AND => self.decode_group_mul_and(bus, ins), OPCG_MUL_AND => self.decode_group_mul_and(ins),
OPCG_ADD => self.decode_group_add(bus, ins), OPCG_ADD => self.decode_group_add(ins),
OPCG_SHIFT => self.decode_group_shift(bus, ins), OPCG_SHIFT => self.decode_group_shift(ins),
OPCG_FLINE => Ok(Instruction::UnimplementedF(ins)), OPCG_FLINE => Ok(Instruction::UnimplementedF(ins)),
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)), _ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
} }
} }
#[inline] #[inline]
fn decode_group_bit_ops(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_bit_ops(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let optype = (ins & 0x0F00) >> 8; let optype = (ins & 0x0F00) >> 8;
if (ins & 0x13F) == 0x03C { if (ins & 0x13F) == 0x03C {
match (ins & 0x00C0) >> 6 { match (ins & 0x00C0) >> 6 {
0b00 => { 0b00 => {
let data = self.read_instruction_word(bus)?; let data = self.read_instruction_word()?;
match optype { match optype {
0b0000 => Ok(Instruction::ORtoCCR(data as u8)), 0b0000 => Ok(Instruction::ORtoCCR(data as u8)),
0b0010 => Ok(Instruction::ANDtoCCR(data as u8)), 0b0010 => Ok(Instruction::ANDtoCCR(data as u8)),
@ -113,7 +161,7 @@ impl M68kDecoder {
} }
}, },
0b01 => { 0b01 => {
let data = self.read_instruction_word(bus)?; let data = self.read_instruction_word()?;
match optype { match optype {
0b0000 => Ok(Instruction::ORtoSR(data)), 0b0000 => Ok(Instruction::ORtoSR(data)),
0b0010 => Ok(Instruction::ANDtoSR(data)), 0b0010 => Ok(Instruction::ANDtoSR(data)),
@ -128,16 +176,16 @@ impl M68kDecoder {
let areg = get_low_reg(ins); let areg = get_low_reg(ins);
let dir = if (ins & 0x0080) == 0 { Direction::FromTarget } else { Direction::ToTarget }; let dir = if (ins & 0x0080) == 0 { Direction::FromTarget } else { Direction::ToTarget };
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
let offset = self.read_instruction_word(bus)? as i16; let offset = self.read_instruction_word()? as i16;
Ok(Instruction::MOVEP(dreg, areg, offset, size, dir)) Ok(Instruction::MOVEP(dreg, areg, offset, size, dir))
} else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 { } else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 {
let bitnum = if (ins & 0x0100) == 0x0100 { let bitnum = if (ins & 0x0100) == 0x0100 {
Target::DirectDReg(get_high_reg(ins)) Target::DirectDReg(get_high_reg(ins))
} else { } else {
Target::Immediate(self.read_instruction_word(bus)? as u32) Target::Immediate(self.read_instruction_word()? as u32)
}; };
let target = self.decode_lower_effective_address(bus, ins, Some(Size::Byte))?; let target = self.decode_lower_effective_address(ins, Some(Size::Byte))?;
let size = match target { let size = match target {
Target::DirectAReg(_) | Target::DirectDReg(_) => Size::Long, Target::DirectAReg(_) | Target::DirectDReg(_) => Size::Long,
_ => Size::Byte, _ => Size::Byte,
@ -153,12 +201,12 @@ impl M68kDecoder {
} else { } else {
let size = get_size(ins); let size = get_size(ins);
let data = match size { let data = match size {
Some(Size::Byte) => self.read_instruction_word(bus)? as u32 & 0xFF, Some(Size::Byte) => self.read_instruction_word()? as u32 & 0xFF,
Some(Size::Word) => self.read_instruction_word(bus)? as u32, Some(Size::Word) => self.read_instruction_word()? as u32,
Some(Size::Long) => self.read_instruction_long(bus)?, Some(Size::Long) => self.read_instruction_long()?,
None => return Err(M68kError::Exception(Exceptions::IllegalInstruction)), None => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
}; };
let target = self.decode_lower_effective_address(bus, ins, size)?; let target = self.decode_lower_effective_address(ins, size)?;
match optype { match optype {
0b0000 => Ok(Instruction::OR(Target::Immediate(data), target, size.unwrap())), 0b0000 => Ok(Instruction::OR(Target::Immediate(data), target, size.unwrap())),
@ -173,16 +221,16 @@ impl M68kDecoder {
} }
#[inline] #[inline]
fn decode_group_move_byte(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_move_byte(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let src = self.decode_lower_effective_address(bus, ins, Some(Size::Byte))?; let src = self.decode_lower_effective_address(ins, Some(Size::Byte))?;
let dest = self.decode_upper_effective_address(bus, ins, Some(Size::Byte))?; let dest = self.decode_upper_effective_address(ins, Some(Size::Byte))?;
Ok(Instruction::MOVE(src, dest, Size::Byte)) Ok(Instruction::MOVE(src, dest, Size::Byte))
} }
#[inline] #[inline]
fn decode_group_move_long(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_move_long(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let src = self.decode_lower_effective_address(bus, ins, Some(Size::Long))?; let src = self.decode_lower_effective_address(ins, Some(Size::Long))?;
let dest = self.decode_upper_effective_address(bus, ins, Some(Size::Long))?; let dest = self.decode_upper_effective_address(ins, Some(Size::Long))?;
if let Target::DirectAReg(reg) = dest { if let Target::DirectAReg(reg) = dest {
Ok(Instruction::MOVEA(src, reg, Size::Long)) Ok(Instruction::MOVEA(src, reg, Size::Long))
} else { } else {
@ -191,9 +239,9 @@ impl M68kDecoder {
} }
#[inline] #[inline]
fn decode_group_move_word(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_move_word(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let src = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; let src = self.decode_lower_effective_address(ins, Some(Size::Word))?;
let dest = self.decode_upper_effective_address(bus, ins, Some(Size::Word))?; let dest = self.decode_upper_effective_address(ins, Some(Size::Word))?;
if let Target::DirectAReg(reg) = dest { if let Target::DirectAReg(reg) = dest {
Ok(Instruction::MOVEA(src, reg, Size::Word)) Ok(Instruction::MOVEA(src, reg, Size::Word))
} else { } else {
@ -202,7 +250,7 @@ impl M68kDecoder {
} }
#[inline] #[inline]
fn decode_group_misc(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_misc(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let ins_0f00 = ins & 0xF00; let ins_0f00 = ins & 0xF00;
let ins_00f0 = ins & 0x0F0; let ins_00f0 = ins & 0x0F0;
@ -210,38 +258,38 @@ impl M68kDecoder {
if (ins & 0x040) == 0 { if (ins & 0x040) == 0 {
let size = match get_size(ins) { let size = match get_size(ins) {
Some(Size::Word) => Size::Word, Some(Size::Word) => Size::Word,
Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long, Some(Size::Long) if self.decoder.cputype >= M68kType::MC68020 => Size::Long,
// On the 68000, long words in CHK are not supported, but the opcode maps to the word size instruction // On the 68000, long words in CHK are not supported, but the opcode maps to the word size instruction
Some(Size::Long) => Size::Word, Some(Size::Long) => Size::Word,
_ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)), _ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
}; };
let reg = get_high_reg(ins); let reg = get_high_reg(ins);
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
Ok(Instruction::CHK(target, reg, size)) Ok(Instruction::CHK(target, reg, size))
} else { } else {
let src = self.decode_lower_effective_address(bus, ins, None)?; let src = self.decode_lower_effective_address(ins, None)?;
let dest = get_high_reg(ins); let dest = get_high_reg(ins);
Ok(Instruction::LEA(src, dest)) Ok(Instruction::LEA(src, dest))
} }
} else if (ins & 0xB80) == 0x880 && (ins & 0x038) != 0 { } else if (ins & 0xB80) == 0x880 && (ins & 0x038) != 0 {
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
let data = self.read_instruction_word(bus)?; let data = self.read_instruction_word()?;
let target = self.decode_lower_effective_address(bus, ins, None)?; let target = self.decode_lower_effective_address(ins, None)?;
let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget }; let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget };
Ok(Instruction::MOVEM(target, size, dir, data)) Ok(Instruction::MOVEM(target, size, dir, data))
} else if (ins & 0xF80) == 0xC00 && self.cputype >= M68kType::MC68020 { } else if (ins & 0xF80) == 0xC00 && self.decoder.cputype >= M68kType::MC68020 {
let extension = self.read_instruction_word(bus)?; let extension = self.read_instruction_word()?;
let reg_h = if (extension & 0x0400) != 0 { Some(get_low_reg(ins)) } else { None }; let reg_h = if (extension & 0x0400) != 0 { Some(get_low_reg(ins)) } else { None };
let reg_l = ((extension & 0x7000) >> 12) as u8; let reg_l = ((extension & 0x7000) >> 12) as u8;
let target = self.decode_lower_effective_address(bus, ins, Some(Size::Long))?; let target = self.decode_lower_effective_address(ins, Some(Size::Long))?;
let sign = if (ins & 0x0800) == 0 { Sign::Unsigned } else { Sign::Signed }; let sign = if (ins & 0x0800) == 0 { Sign::Unsigned } else { Sign::Signed };
match (ins & 0x040) == 0 { match (ins & 0x040) == 0 {
true => Ok(Instruction::MULL(target, reg_h, reg_l, sign)), true => Ok(Instruction::MULL(target, reg_h, reg_l, sign)),
false => Ok(Instruction::DIVL(target, reg_h, reg_l, sign)), false => Ok(Instruction::DIVL(target, reg_h, reg_l, sign)),
} }
} else if (ins & 0x800) == 0 { } else if (ins & 0x800) == 0 {
let target = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; let target = self.decode_lower_effective_address(ins, Some(Size::Word))?;
match (ins & 0x0700) >> 8 { match (ins & 0x0700) >> 8 {
0b000 => { 0b000 => {
match get_size(ins) { match get_size(ins) {
@ -252,7 +300,7 @@ impl M68kDecoder {
0b010 => { 0b010 => {
match get_size(ins) { match get_size(ins) {
Some(size) => Ok(Instruction::CLR(target, size)), Some(size) => Ok(Instruction::CLR(target, size)),
None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)), None if self.decoder.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)),
None => Err(M68kError::Exception(Exceptions::IllegalInstruction)), None => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
} }
}, },
@ -274,12 +322,12 @@ impl M68kDecoder {
let opmode = (ins & 0x01C0) >> 6; let opmode = (ins & 0x01C0) >> 6;
let mode = get_low_mode(ins); let mode = get_low_mode(ins);
match (opmode, mode) { match (opmode, mode) {
(0b000, 0b001) if self.cputype >= M68kType::MC68020 => { (0b000, 0b001) if self.decoder.cputype >= M68kType::MC68020 => {
let data = self.read_instruction_long(bus)? as i32; let data = self.read_instruction_long()? as i32;
Ok(Instruction::LINK(get_low_reg(ins), data)) Ok(Instruction::LINK(get_low_reg(ins), data))
}, },
(0b000, _) => { (0b000, _) => {
let target = self.decode_lower_effective_address(bus, ins, Some(Size::Byte))?; let target = self.decode_lower_effective_address(ins, Some(Size::Byte))?;
Ok(Instruction::NBCD(target)) Ok(Instruction::NBCD(target))
}, },
(0b001, 0b000) => { (0b001, 0b000) => {
@ -289,7 +337,7 @@ impl M68kDecoder {
Ok(Instruction::BKPT(get_low_reg(ins))) Ok(Instruction::BKPT(get_low_reg(ins)))
}, },
(0b001, _) => { (0b001, _) => {
let target = self.decode_lower_effective_address(bus, ins, None)?; let target = self.decode_lower_effective_address(ins, None)?;
Ok(Instruction::PEA(target)) Ok(Instruction::PEA(target))
}, },
(0b010, 0b000) => { (0b010, 0b000) => {
@ -307,7 +355,7 @@ impl M68kDecoder {
if (ins & 0x0FF) == 0xFC { if (ins & 0x0FF) == 0xFC {
Ok(Instruction::ILLEGAL) Ok(Instruction::ILLEGAL)
} else { } else {
let target = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; let target = self.decode_lower_effective_address(ins, Some(Size::Word))?;
match get_size(ins) { match get_size(ins) {
Some(size) => Ok(Instruction::TST(target, size)), Some(size) => Ok(Instruction::TST(target, size)),
None => Ok(Instruction::TAS(target)), None => Ok(Instruction::TAS(target)),
@ -315,7 +363,7 @@ impl M68kDecoder {
} }
} else if ins_0f00 == 0xE00 { } else if ins_0f00 == 0xE00 {
if (ins & 0x80) == 0x80 { if (ins & 0x80) == 0x80 {
let target = self.decode_lower_effective_address(bus, ins, None)?; let target = self.decode_lower_effective_address(ins, None)?;
if (ins & 0b01000000) == 0 { if (ins & 0b01000000) == 0 {
Ok(Instruction::JSR(target)) Ok(Instruction::JSR(target))
} else { } else {
@ -326,7 +374,7 @@ impl M68kDecoder {
} else if ins_00f0 == 0x50 { } else if ins_00f0 == 0x50 {
let reg = get_low_reg(ins); let reg = get_low_reg(ins);
if (ins & 0b1000) == 0 { if (ins & 0b1000) == 0 {
let data = (self.read_instruction_word(bus)? as i16) as i32; let data = (self.read_instruction_word()? as i16) as i32;
Ok(Instruction::LINK(reg, data)) Ok(Instruction::LINK(reg, data))
} else { } else {
Ok(Instruction::UNLK(reg)) Ok(Instruction::UNLK(reg))
@ -340,20 +388,20 @@ impl M68kDecoder {
0x70 => Ok(Instruction::RESET), 0x70 => Ok(Instruction::RESET),
0x71 => Ok(Instruction::NOP), 0x71 => Ok(Instruction::NOP),
0x72 => { 0x72 => {
let data = self.read_instruction_word(bus)?; let data = self.read_instruction_word()?;
Ok(Instruction::STOP(data)) Ok(Instruction::STOP(data))
}, },
0x73 => Ok(Instruction::RTE), 0x73 => Ok(Instruction::RTE),
0x74 if self.cputype >= M68kType::MC68010 => { 0x74 if self.decoder.cputype >= M68kType::MC68010 => {
let offset = self.read_instruction_word(bus)? as i16; let offset = self.read_instruction_word()? as i16;
Ok(Instruction::RTD(offset)) Ok(Instruction::RTD(offset))
}, },
0x75 => Ok(Instruction::RTS), 0x75 => Ok(Instruction::RTS),
0x76 => Ok(Instruction::TRAPV), 0x76 => Ok(Instruction::TRAPV),
0x77 => Ok(Instruction::RTR), 0x77 => Ok(Instruction::RTR),
0x7A | 0x7B if self.cputype >= M68kType::MC68010 => { 0x7A | 0x7B if self.decoder.cputype >= M68kType::MC68010 => {
let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget }; let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget };
let ins2 = self.read_instruction_word(bus)?; let ins2 = self.read_instruction_word()?;
let target = match ins2 & 0x8000 { let target = match ins2 & 0x8000 {
0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8), 0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8),
_ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8), _ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8),
@ -373,10 +421,10 @@ impl M68kDecoder {
} }
#[inline] #[inline]
fn decode_group_addq_subq(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_addq_subq(&mut self, ins: u16) -> Result<Instruction, M68kError> {
match get_size(ins) { match get_size(ins) {
Some(size) => { Some(size) => {
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
let mut data = ((ins & 0x0E00) >> 9) as u32; let mut data = ((ins & 0x0E00) >> 9) as u32;
if data == 0 { if data == 0 {
data = 8; data = 8;
@ -400,10 +448,10 @@ impl M68kDecoder {
if mode == 0b001 { if mode == 0b001 {
let reg = get_low_reg(ins); let reg = get_low_reg(ins);
let disp = self.read_instruction_word(bus)? as i16; let disp = self.read_instruction_word()? as i16;
Ok(Instruction::DBcc(condition, reg, disp)) Ok(Instruction::DBcc(condition, reg, disp))
} else { } else {
let target = self.decode_lower_effective_address(bus, ins, Some(Size::Byte))?; let target = self.decode_lower_effective_address(ins, Some(Size::Byte))?;
Ok(Instruction::Scc(condition, target)) Ok(Instruction::Scc(condition, target))
} }
}, },
@ -411,12 +459,12 @@ impl M68kDecoder {
} }
#[inline] #[inline]
fn decode_group_branch(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_branch(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let mut disp = ((ins & 0xFF) as i8) as i32; let mut disp = ((ins & 0xFF) as i8) as i32;
if disp == 0 { if disp == 0 {
disp = (self.read_instruction_word(bus)? as i16) as i32; disp = (self.read_instruction_word()? as i16) as i32;
} else if disp == -1 && self.cputype >= M68kType::MC68020 { } else if disp == -1 && self.decoder.cputype >= M68kType::MC68020 {
disp = self.read_instruction_long(bus)? as i32; disp = self.read_instruction_long()? as i32;
} }
let condition = get_condition(ins); let condition = get_condition(ins);
match condition { match condition {
@ -427,7 +475,7 @@ impl M68kDecoder {
} }
#[inline] #[inline]
fn decode_group_moveq(&mut self, _bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_moveq(&mut self, ins: u16) -> Result<Instruction, M68kError> {
if (ins & 0x0100) != 0 { if (ins & 0x0100) != 0 {
return Err(M68kError::Exception(Exceptions::IllegalInstruction)); return Err(M68kError::Exception(Exceptions::IllegalInstruction));
} }
@ -437,7 +485,7 @@ impl M68kDecoder {
} }
#[inline] #[inline]
fn decode_group_div_or(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_div_or(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let size = get_size(ins); let size = get_size(ins);
if (ins & 0x1F0) == 0x100 { if (ins & 0x1F0) == 0x100 {
@ -450,18 +498,18 @@ impl M68kDecoder {
} }
} else if let Some(size) = size { } else if let Some(size) = size {
let data_reg = Target::DirectDReg(get_high_reg(ins)); let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(bus, ins, Some(size))?; let effective_addr = self.decode_lower_effective_address(ins, Some(size))?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) }; let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::OR(from, to, size)) Ok(Instruction::OR(from, to, size))
} else { } else {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed }; let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let effective_addr = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; let effective_addr = self.decode_lower_effective_address(ins, Some(Size::Word))?;
Ok(Instruction::DIVW(effective_addr, get_high_reg(ins), sign)) Ok(Instruction::DIVW(effective_addr, get_high_reg(ins), sign))
} }
} }
#[inline] #[inline]
fn decode_group_sub(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_sub(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let reg = get_high_reg(ins); let reg = get_high_reg(ins);
let dir = (ins & 0x0100) >> 8; let dir = (ins & 0x0100) >> 8;
let size = get_size(ins); let size = get_size(ins);
@ -475,7 +523,7 @@ impl M68kDecoder {
false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)),
} }
} else { } else {
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
if dir == 0 { if dir == 0 {
Ok(Instruction::SUB(target, Target::DirectDReg(reg), size)) Ok(Instruction::SUB(target, Target::DirectDReg(reg), size))
} else { } else {
@ -485,14 +533,14 @@ impl M68kDecoder {
}, },
None => { None => {
let size = if dir == 0 { Size::Word } else { Size::Long }; let size = if dir == 0 { Size::Word } else { Size::Long };
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
Ok(Instruction::SUBA(target, reg, size)) Ok(Instruction::SUBA(target, reg, size))
}, },
} }
} }
#[inline] #[inline]
fn decode_group_cmp_eor(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_cmp_eor(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let reg = get_high_reg(ins); let reg = get_high_reg(ins);
let optype = (ins & 0x0100) >> 8; let optype = (ins & 0x0100) >> 8;
let size = get_size(ins); let size = get_size(ins);
@ -501,17 +549,17 @@ impl M68kDecoder {
if get_low_mode(ins) == 0b001 { if get_low_mode(ins) == 0b001 {
Ok(Instruction::CMP(Target::IndirectARegInc(get_low_reg(ins)), Target::IndirectARegInc(reg), size)) Ok(Instruction::CMP(Target::IndirectARegInc(get_low_reg(ins)), Target::IndirectARegInc(reg), size))
} else { } else {
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
Ok(Instruction::EOR(Target::DirectDReg(reg), target, size)) Ok(Instruction::EOR(Target::DirectDReg(reg), target, size))
} }
}, },
(0b0, Some(size)) => { (0b0, Some(size)) => {
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
Ok(Instruction::CMP(target, Target::DirectDReg(reg), size)) Ok(Instruction::CMP(target, Target::DirectDReg(reg), size))
}, },
(_, None) => { (_, None) => {
let size = if optype == 0 { Size::Word } else { Size::Long }; let size = if optype == 0 { Size::Word } else { Size::Long };
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
Ok(Instruction::CMPA(target, reg, size)) Ok(Instruction::CMPA(target, reg, size))
}, },
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)), _ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
@ -519,7 +567,7 @@ impl M68kDecoder {
} }
#[inline] #[inline]
fn decode_group_mul_and(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_mul_and(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let size = get_size(ins); let size = get_size(ins);
if (ins & 0b0001_1111_0000) == 0b0001_0000_0000 { if (ins & 0b0001_1111_0000) == 0b0001_0000_0000 {
@ -541,18 +589,18 @@ impl M68kDecoder {
} }
} else if let Some(size) = size { } else if let Some(size) = size {
let data_reg = Target::DirectDReg(get_high_reg(ins)); let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(bus, ins, Some(size))?; let effective_addr = self.decode_lower_effective_address(ins, Some(size))?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) }; let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::AND(from, to, size)) Ok(Instruction::AND(from, to, size))
} else { } else {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed }; let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let effective_addr = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; let effective_addr = self.decode_lower_effective_address(ins, Some(Size::Word))?;
Ok(Instruction::MULW(effective_addr, get_high_reg(ins), sign)) Ok(Instruction::MULW(effective_addr, get_high_reg(ins), sign))
} }
} }
#[inline] #[inline]
fn decode_group_add(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_add(&mut self, ins: u16) -> Result<Instruction, M68kError> {
let reg = get_high_reg(ins); let reg = get_high_reg(ins);
let dir = (ins & 0x0100) >> 8; let dir = (ins & 0x0100) >> 8;
let size = get_size(ins); let size = get_size(ins);
@ -566,7 +614,7 @@ impl M68kDecoder {
false => Ok(Instruction::ADDX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), false => Ok(Instruction::ADDX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)),
} }
} else { } else {
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
if dir == 0 { if dir == 0 {
Ok(Instruction::ADD(target, Target::DirectDReg(reg), size)) Ok(Instruction::ADD(target, Target::DirectDReg(reg), size))
} else { } else {
@ -576,13 +624,13 @@ impl M68kDecoder {
}, },
None => { None => {
let size = if dir == 0 { Size::Word } else { Size::Long }; let size = if dir == 0 { Size::Word } else { Size::Long };
let target = self.decode_lower_effective_address(bus, ins, Some(size))?; let target = self.decode_lower_effective_address(ins, Some(size))?;
Ok(Instruction::ADDA(target, reg, size)) Ok(Instruction::ADDA(target, reg, size))
}, },
} }
} }
fn decode_group_shift(&mut self, bus: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> { fn decode_group_shift(&mut self, ins: u16) -> Result<Instruction, M68kError> {
match get_size(ins) { match get_size(ins) {
Some(size) => { Some(size) => {
let target = Target::DirectDReg(get_low_reg(ins)); let target = Target::DirectDReg(get_low_reg(ins));
@ -613,7 +661,7 @@ impl M68kDecoder {
}, },
None => { None => {
if (ins & 0x800) == 0 { if (ins & 0x800) == 0 {
let target = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; let target = self.decode_lower_effective_address(ins, Some(Size::Word))?;
let count = Target::Immediate(1); let count = Target::Immediate(1);
let size = Size::Word; let size = Size::Word;
@ -634,9 +682,9 @@ impl M68kDecoder {
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)), _ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
} }
} }
} else if self.cputype > M68kType::MC68020 { } else if self.decoder.cputype > M68kType::MC68020 {
// Bitfield instructions (MC68020+) // Bitfield instructions (MC68020+)
let ext = self.read_instruction_word(bus)?; let ext = self.read_instruction_word()?;
let reg = ((ext & 0x7000) >> 12) as u8; let reg = ((ext & 0x7000) >> 12) as u8;
let offset = match (ext & 0x0800) == 0 { let offset = match (ext & 0x0800) == 0 {
@ -649,7 +697,7 @@ impl M68kDecoder {
false => RegOrImmediate::DReg((ext & 0x0007) as u8), false => RegOrImmediate::DReg((ext & 0x0007) as u8),
}; };
let target = self.decode_lower_effective_address(bus, ins, Some(Size::Word))?; let target = self.decode_lower_effective_address(ins, Some(Size::Word))?;
match (ins & 0x0700) >> 8 { match (ins & 0x0700) >> 8 {
0b010 => Ok(Instruction::BFCHG(target, offset, width)), 0b010 => Ok(Instruction::BFCHG(target, offset, width)),
0b100 => Ok(Instruction::BFCLR(target, offset, width)), 0b100 => Ok(Instruction::BFCLR(target, offset, width)),
@ -668,42 +716,42 @@ impl M68kDecoder {
} }
} }
fn read_instruction_word(&mut self, bus: &mut M68kBusPort) -> Result<u16, M68kError> { fn read_instruction_word(&mut self) -> Result<u16, M68kError> {
let word = bus.read_instruction_word(self.is_supervisor, self.end)?; let word = self.memory.read_instruction_word(self.port, self.decoder.is_supervisor, self.decoder.end)?;
self.end += 2; self.decoder.end += 2;
Ok(word) Ok(word)
} }
fn read_instruction_long(&mut self, bus: &mut M68kBusPort) -> Result<u32, M68kError> { fn read_instruction_long(&mut self) -> Result<u32, M68kError> {
let word = bus.read_instruction_long(self.is_supervisor, self.end)?; let word = self.memory.read_instruction_long(self.port, self.decoder.is_supervisor, self.decoder.end)?;
self.end += 4; self.decoder.end += 4;
Ok(word) Ok(word)
} }
fn decode_lower_effective_address(&mut self, bus: &mut M68kBusPort, ins: u16, size: Option<Size>) -> Result<Target, M68kError> { fn decode_lower_effective_address(&mut self, ins: u16, size: Option<Size>) -> Result<Target, M68kError> {
let reg = get_low_reg(ins); let reg = get_low_reg(ins);
let mode = get_low_mode(ins); let mode = get_low_mode(ins);
self.get_mode_as_target(bus, mode, reg, size) self.get_mode_as_target(mode, reg, size)
} }
fn decode_upper_effective_address(&mut self, bus: &mut M68kBusPort, ins: u16, size: Option<Size>) -> Result<Target, M68kError> { fn decode_upper_effective_address(&mut self, ins: u16, size: Option<Size>) -> Result<Target, M68kError> {
let reg = get_high_reg(ins); let reg = get_high_reg(ins);
let mode = get_high_mode(ins); let mode = get_high_mode(ins);
self.get_mode_as_target(bus, mode, reg, size) self.get_mode_as_target(mode, reg, size)
} }
fn get_extension_displacement(&mut self, bus: &mut M68kBusPort, select: u16) -> Result<i32, M68kError> { fn get_extension_displacement(&mut self, select: u16) -> Result<i32, M68kError> {
let result = match select { let result = match select {
0b00 | 0b01 => 0, 0b00 | 0b01 => 0,
0b10 => sign_extend_to_long(self.read_instruction_word(bus)? as u32, Size::Word), 0b10 => sign_extend_to_long(self.read_instruction_word()? as u32, Size::Word),
0b11 => self.read_instruction_long(bus)? as i32, 0b11 => self.read_instruction_long()? as i32,
_ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)), _ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
}; };
Ok(result) Ok(result)
} }
fn decode_extension_word(&mut self, bus: &mut M68kBusPort, areg: Option<u8>) -> Result<Target, M68kError> { fn decode_extension_word(&mut self, areg: Option<u8>) -> Result<Target, M68kError> {
let brief_extension = self.read_instruction_word(bus)?; let brief_extension = self.read_instruction_word()?;
let use_brief = (brief_extension & 0x0100) == 0; let use_brief = (brief_extension & 0x0100) == 0;
@ -712,7 +760,7 @@ impl M68kDecoder {
let xreg = if (brief_extension & 0x8000) == 0 { XRegister::DReg(xreg_num) } else { XRegister::AReg(xreg_num) }; let xreg = if (brief_extension & 0x8000) == 0 { XRegister::DReg(xreg_num) } else { XRegister::AReg(xreg_num) };
let size = if (brief_extension & 0x0800) == 0 { Size::Word } else { Size::Long }; let size = if (brief_extension & 0x0800) == 0 { Size::Word } else { Size::Long };
if self.cputype <= M68kType::MC68010 { if self.decoder.cputype <= M68kType::MC68010 {
let index_reg = IndexRegister { xreg, scale: 0, size }; let index_reg = IndexRegister { xreg, scale: 0, size };
let displacement = sign_extend_to_long((brief_extension & 0x00FF) as u32, Size::Byte); let displacement = sign_extend_to_long((brief_extension & 0x00FF) as u32, Size::Byte);
@ -744,8 +792,8 @@ impl M68kDecoder {
(true, Some(areg)) => BaseRegister::AReg(areg), (true, Some(areg)) => BaseRegister::AReg(areg),
}; };
let opt_index_reg = if use_index { Some(index_reg) } else { None }; let opt_index_reg = if use_index { Some(index_reg) } else { None };
let base_disp = self.get_extension_displacement(bus, (brief_extension & 0x0030) >> 4)?; let base_disp = self.get_extension_displacement((brief_extension & 0x0030) >> 4)?;
let outer_disp = self.get_extension_displacement(bus, brief_extension & 0x0003)?; let outer_disp = self.get_extension_displacement(brief_extension & 0x0003)?;
match (use_sub_indirect, pre_not_post) { match (use_sub_indirect, pre_not_post) {
(false, _) => Ok(Target::IndirectRegOffset(opt_base_reg, opt_index_reg, base_disp)), (false, _) => Ok(Target::IndirectRegOffset(opt_base_reg, opt_index_reg, base_disp)),
@ -755,7 +803,7 @@ impl M68kDecoder {
} }
} }
pub(super) fn get_mode_as_target(&mut self, bus: &mut M68kBusPort, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, M68kError> { pub(super) fn get_mode_as_target(&mut self, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, M68kError> {
let value = match mode { let value = match mode {
0b000 => Target::DirectDReg(reg), 0b000 => Target::DirectDReg(reg),
0b001 => Target::DirectAReg(reg), 0b001 => Target::DirectAReg(reg),
@ -763,33 +811,33 @@ impl M68kDecoder {
0b011 => Target::IndirectARegInc(reg), 0b011 => Target::IndirectARegInc(reg),
0b100 => Target::IndirectARegDec(reg), 0b100 => Target::IndirectARegDec(reg),
0b101 => { 0b101 => {
let displacement = sign_extend_to_long(self.read_instruction_word(bus)? as u32, Size::Word); let displacement = sign_extend_to_long(self.read_instruction_word()? as u32, Size::Word);
Target::IndirectRegOffset(BaseRegister::AReg(reg), None, displacement) Target::IndirectRegOffset(BaseRegister::AReg(reg), None, displacement)
}, },
0b110 => { 0b110 => {
self.decode_extension_word(bus, Some(reg))? self.decode_extension_word(Some(reg))?
}, },
0b111 => { 0b111 => {
match reg { match reg {
0b000 => { 0b000 => {
let value = sign_extend_to_long(self.read_instruction_word(bus)? as u32, Size::Word) as u32; let value = sign_extend_to_long(self.read_instruction_word()? as u32, Size::Word) as u32;
Target::IndirectMemory(value, Size::Word) Target::IndirectMemory(value, Size::Word)
}, },
0b001 => { 0b001 => {
let value = self.read_instruction_long(bus)?; let value = self.read_instruction_long()?;
Target::IndirectMemory(value, Size::Long) Target::IndirectMemory(value, Size::Long)
}, },
0b010 => { 0b010 => {
let displacement = sign_extend_to_long(self.read_instruction_word(bus)? as u32, Size::Word); let displacement = sign_extend_to_long(self.read_instruction_word()? as u32, Size::Word);
Target::IndirectRegOffset(BaseRegister::PC, None, displacement) Target::IndirectRegOffset(BaseRegister::PC, None, displacement)
}, },
0b011 => { 0b011 => {
self.decode_extension_word(bus, None)? self.decode_extension_word(None)?
}, },
0b100 => { 0b100 => {
let data = match size { let data = match size {
Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(bus)? as u32, Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word()? as u32,
Some(Size::Long) => self.read_instruction_long(bus)?, Some(Size::Long) => self.read_instruction_long()?,
None => return Err(M68kError::Exception(Exceptions::IllegalInstruction)), None => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
}; };
Target::Immediate(data) Target::Immediate(data)
@ -802,35 +850,7 @@ impl M68kDecoder {
Ok(value) Ok(value)
} }
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(bus, self.is_supervisor, next) {
Ok(()) => {
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, bus.port.read_beu16(bus.current_clock, self.start as Address).unwrap());
},
_ => { },
}
return;
},
}
}
}
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} ", 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);
}
} }
#[inline(always)] #[inline(always)]

View File

@ -1,7 +1,7 @@
use femtos::{Instant, Duration}; use femtos::{Instant, Duration};
use moa_core::{System, Error, Address, Steppable, Interruptable, Addressable, Debuggable, Transmutable}; use moa_core::{System, Error, Address, Steppable, Interruptable, Addressable, Debuggable, Transmutable, BusPort};
use crate::state::{M68k, M68kType, M68kError, M68kState, ClockCycles, Status, Flags, Exceptions, InterruptPriority}; use crate::state::{M68k, M68kType, M68kError, M68kState, ClockCycles, Status, Flags, Exceptions, InterruptPriority};
use crate::memory::{MemType, MemAccess, M68kBusPort}; use crate::memory::{MemType, MemAccess, M68kBusPort};
@ -38,35 +38,35 @@ pub enum Used {
pub struct M68kCycle { pub struct M68kCycle {
pub decoder: M68kDecoder, pub decoder: M68kDecoder,
pub timing: M68kInstructionTiming, pub timing: M68kInstructionTiming,
pub memory: M68kBusPort,
pub current_clock: Instant, pub current_clock: Instant,
} }
impl M68kCycle { impl M68kCycle {
#[inline]
pub fn default(cputype: M68kType, data_width: u8) -> Self { pub fn default(cputype: M68kType, data_width: u8) -> Self {
Self { Self {
decoder: M68kDecoder::new(cputype, true, 0), decoder: M68kDecoder::new(cputype, true, 0),
timing: M68kInstructionTiming::new(cputype, data_width), timing: M68kInstructionTiming::new(cputype, data_width),
memory: M68kBusPort::new(Instant::START),
current_clock: Instant::START, current_clock: Instant::START,
} }
} }
#[inline]
pub fn new(cpu: &M68k, clock: Instant) -> Self { pub fn new(cpu: &M68k, clock: Instant) -> Self {
let is_supervisor = cpu.state.sr & (Flags:: Supervisor as u16) != 0; 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 { Self {
decoder: M68kDecoder::new(cputype, is_supervisor, pc), decoder: M68kDecoder::new(cpu.info.chip, is_supervisor, cpu.state.pc),
timing: M68kInstructionTiming::new(cputype, data_width), timing: M68kInstructionTiming::new(cpu.info.chip, cpu.info.data_width as u8),
memory: M68kBusPort::new(clock),
current_clock: clock, current_clock: clock,
} }
} }
pub fn begin<'a>(mut self, cpu: &'a mut M68k) -> M68kCycleGuard<'a> { #[inline]
// TODO this port init_cycle must be integrated into the cycle struct instead pub fn begin<'a>(mut self, cpu: &'a mut M68k) -> M68kCycleExecutor<'a> {
cpu.port.init_cycle(self.current_clock); M68kCycleExecutor {
M68kCycleGuard {
state: &mut cpu.state, state: &mut cpu.state,
port: &mut cpu.port, port: &mut cpu.port,
debugger: &mut cpu.debugger, debugger: &mut cpu.debugger,
@ -75,14 +75,15 @@ impl M68kCycle {
} }
} }
pub struct M68kCycleGuard<'a> { pub struct M68kCycleExecutor<'a> {
pub state: &'a mut M68kState, pub state: &'a mut M68kState,
pub port: &'a mut M68kBusPort, pub port: &'a mut BusPort,
pub debugger: &'a mut M68kDebugger, pub debugger: &'a mut M68kDebugger,
pub cycle: M68kCycle, pub cycle: M68kCycle,
} }
impl<'a> M68kCycleGuard<'a> { impl<'a> M68kCycleExecutor<'a> {
#[inline]
pub fn dump_state(&mut self) { pub fn dump_state(&mut self) {
println!("Status: {:?}", self.state.status); println!("Status: {:?}", self.state.status);
println!("PC: {:#010x}", self.state.pc); println!("PC: {:#010x}", self.state.pc);
@ -95,7 +96,7 @@ impl<'a> M68kCycleGuard<'a> {
println!("Current Instruction: {:#010x} {:?}", self.cycle.decoder.start, self.cycle.decoder.instruction); println!("Current Instruction: {:#010x} {:?}", self.cycle.decoder.start, self.cycle.decoder.instruction);
println!(); println!();
self.port.dump_memory(self.state.ssp, 0x40); self.cycle.memory.dump_memory(self.port, self.state.ssp, 0x40);
println!(); println!();
} }
@ -107,10 +108,10 @@ impl<'a> M68kCycleGuard<'a> {
impl Steppable for M68k { impl Steppable for M68k {
fn step(&mut self, system: &System) -> Result<Duration, Error> { fn step(&mut self, system: &System) -> Result<Duration, Error> {
let cycle = M68kCycle::new(self, system.clock); let cycle = M68kCycle::new(self, system.clock);
let mut execution = cycle.begin(self); let mut executor = cycle.begin(self);
let clocks = execution.step(system)?; let clocks = executor.step(system)?;
self.cycle = execution.end(); self.cycle = Some(executor.end());
Ok(self.frequency.period_duration() * clocks as u64) Ok(self.info.frequency.period_duration() * clocks as u64)
} }
fn on_error(&mut self, _system: &System) { fn on_error(&mut self, _system: &System) {
@ -158,26 +159,35 @@ impl From<Error> for M68kError {
} }
} }
impl<'a> M68kCycleGuard<'a> { impl<'a> M68kCycleExecutor<'a> {
#[inline] #[inline]
pub fn step(&mut self, system: &System) -> Result<ClockCycles, M68kError> { pub fn step(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
let result = self.step_one(system);
self.process_error(result, 4)
}
#[inline]
pub fn process_error<T>(&mut self, result: Result<T, M68kError>, ok: T) -> Result<T, M68kError> {
match result {
Ok(value) => Ok(value),
Err(M68kError::Exception(ex)) => {
self.exception(ex as u8, false)?;
Ok(ok)
},
Err(M68kError::Interrupt(ex)) => {
self.exception(ex as u8, false)?;
Ok(ok)
},
Err(err) => Err(err),
}
}
#[inline]
pub fn step_one(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
match self.state.status { match self.state.status {
Status::Init => self.reset_cpu(), Status::Init => self.reset_cpu(),
Status::Stopped => Err(M68kError::Halted), Status::Stopped => Err(M68kError::Halted),
Status::Running => { Status::Running => self.cycle_one(system),
match self.cycle_one(system) {
Ok(diff) => Ok(diff),
Err(M68kError::Exception(ex)) => {
self.exception(ex as u8, false)?;
Ok(4)
},
Err(M68kError::Interrupt(ex)) => {
self.exception(ex as u8, false)?;
Ok(4)
},
Err(err) => Err(err),
}
},
} }
} }
@ -201,6 +211,7 @@ impl<'a> M68kCycleGuard<'a> {
#[inline] #[inline]
pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), M68kError> { pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), M68kError> {
// TODO this could move somewhere else
self.state.pending_ipl = match system.get_interrupt_controller().check() { self.state.pending_ipl = match system.get_interrupt_controller().check() {
(true, priority) => InterruptPriority::from_u8(priority), (true, priority) => InterruptPriority::from_u8(priority),
(false, _) => InterruptPriority::NoInterrupt, (false, _) => InterruptPriority::NoInterrupt,
@ -228,6 +239,35 @@ impl<'a> M68kCycleGuard<'a> {
Ok(()) Ok(())
} }
/*
#[inline]
pub fn check_pending_interrupts2(&mut self, interrupt: Option<(InterruptPriority, u8)>) -> Result<InterruptAcknowledge, M68kError> {
self.state.pending_ipl = interrupt.unwrap_or(InterruptPriority::NoInterrupt);
let current_ipl = self.state.current_ipl as u8;
let pending_ipl = self.state.pending_ipl as u8;
if self.state.pending_ipl != InterruptPriority::NoInterrupt {
let priority_mask = ((self.state.sr & Flags::IntMask as u16) >> 8) as u8;
if (pending_ipl > priority_mask || pending_ipl == 7) && pending_ipl >= current_ipl {
log::debug!("{} interrupt: {} @ {} ns", DEV_NAME, pending_ipl, system.clock.as_duration().as_nanos());
self.state.current_ipl = self.state.pending_ipl;
let acknowledge = self.state.current_ipl;
let ack_num = system.get_interrupt_controller().acknowledge(self.state.current_ipl as u8)?;
self.exception(ack_num, true)?;
return Ok(());
}
}
if pending_ipl < current_ipl {
self.state.current_ipl = self.state.pending_ipl;
}
Ok(())
}
*/
pub fn exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError> { pub fn exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError> {
log::debug!("{}: raising exception {}", DEV_NAME, number); log::debug!("{}: raising exception {}", DEV_NAME, number);
@ -247,9 +287,9 @@ impl<'a> M68kCycleGuard<'a> {
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 sr = self.state.sr;
let ins_word = self.cycle.decoder.instruction_word; let ins_word = self.cycle.decoder.instruction_word;
let extra_code = self.port.request.get_type_code(); let extra_code = self.cycle.memory.request.get_type_code();
let fault_size = self.port.request.size.in_bytes(); let fault_size = self.cycle.memory.request.size.in_bytes();
let fault_address = self.port.request.address; let fault_address = self.cycle.memory.request.address;
// Changes to the flags must happen after the previous value has been pushed to the stack // Changes to the flags must happen after the previous value has been pushed to the stack
self.set_flag(Flags::Supervisor, true); self.set_flag(Flags::Supervisor, true);
@ -275,7 +315,7 @@ impl<'a> M68kCycleGuard<'a> {
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; let sr = self.state.sr;
self.port.request.i_n_bit = true; self.cycle.memory.request.i_n_bit = true;
// Changes to the flags must happen after the previous value has been pushed to the stack // Changes to the flags must happen after the previous value has been pushed to the stack
self.set_flag(Flags::Supervisor, true); self.set_flag(Flags::Supervisor, true);
@ -308,7 +348,7 @@ impl<'a> M68kCycleGuard<'a> {
#[inline] #[inline]
pub fn decode_next(&mut self) -> Result<(), M68kError> { pub fn decode_next(&mut self) -> Result<(), M68kError> {
let is_supervisor = self.is_supervisor(); let is_supervisor = self.is_supervisor();
self.cycle.decoder.decode_at(&mut self.port, is_supervisor, self.state.pc)?; self.cycle.decoder.decode_at(&mut self.port, &mut self.cycle.memory, is_supervisor, self.state.pc)?;
self.cycle.timing.add_instruction(&self.cycle.decoder.instruction); self.cycle.timing.add_instruction(&self.cycle.decoder.instruction);
@ -1613,25 +1653,25 @@ impl<'a> M68kCycleGuard<'a> {
} }
fn get_address_sized(&mut self, addr: Address, size: Size) -> Result<u32, M68kError> { fn get_address_sized(&mut self, addr: Address, size: Size) -> Result<u32, M68kError> {
self.port.read_data_sized(self.is_supervisor(), addr, size) self.cycle.memory.read_data_sized(self.port, self.is_supervisor(), addr, size)
} }
fn set_address_sized(&mut self, addr: Address, value: u32, size: Size) -> Result<(), M68kError> { fn set_address_sized(&mut self, addr: Address, value: u32, size: Size) -> Result<(), M68kError> {
self.port.write_data_sized(self.is_supervisor(), addr, value, size) self.cycle.memory.write_data_sized(self.port, self.is_supervisor(), addr, value, size)
} }
fn push_word(&mut self, value: u16) -> Result<(), M68kError> { fn push_word(&mut self, value: u16) -> Result<(), M68kError> {
*self.get_stack_pointer_mut() -= 2; *self.get_stack_pointer_mut() -= 2;
let addr = *self.get_stack_pointer_mut(); let addr = *self.get_stack_pointer_mut();
self.port.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Write, MemType::Data, false)?; self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Write, MemType::Data, false)?;
self.port.port.write_beu16(self.cycle.current_clock, addr as Address, value)?; self.port.write_beu16(self.cycle.current_clock, addr as Address, value)?;
Ok(()) Ok(())
} }
fn pop_word(&mut self) -> Result<u16, M68kError> { fn pop_word(&mut self) -> Result<u16, M68kError> {
let addr = *self.get_stack_pointer_mut(); let addr = *self.get_stack_pointer_mut();
self.port.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Read, MemType::Data, false)?; self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Read, MemType::Data, false)?;
let value = self.port.port.read_beu16(self.cycle.current_clock, addr as Address)?; let value = self.port.read_beu16(self.cycle.current_clock, addr as Address)?;
*self.get_stack_pointer_mut() += 2; *self.get_stack_pointer_mut() += 2;
Ok(value) Ok(value)
} }
@ -1639,22 +1679,22 @@ impl<'a> M68kCycleGuard<'a> {
fn push_long(&mut self, value: u32) -> Result<(), M68kError> { fn push_long(&mut self, value: u32) -> Result<(), M68kError> {
*self.get_stack_pointer_mut() -= 4; *self.get_stack_pointer_mut() -= 4;
let addr = *self.get_stack_pointer_mut(); let addr = *self.get_stack_pointer_mut();
self.port.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Write, MemType::Data, false)?; self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Write, MemType::Data, false)?;
self.port.port.write_beu32(self.cycle.current_clock, addr as Address, value)?; self.port.write_beu32(self.cycle.current_clock, addr as Address, value)?;
Ok(()) Ok(())
} }
fn pop_long(&mut self) -> Result<u32, M68kError> { fn pop_long(&mut self) -> Result<u32, M68kError> {
let addr = *self.get_stack_pointer_mut(); let addr = *self.get_stack_pointer_mut();
self.port.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Read, MemType::Data, false)?; self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Read, MemType::Data, false)?;
let value = self.port.port.read_beu32(self.cycle.current_clock, addr as Address)?; let value = self.port.read_beu32(self.cycle.current_clock, addr as Address)?;
*self.get_stack_pointer_mut() += 4; *self.get_stack_pointer_mut() += 4;
Ok(value) Ok(value)
} }
fn set_pc(&mut self, value: u32) -> Result<(), M68kError> { fn set_pc(&mut self, value: u32) -> Result<(), M68kError> {
self.state.pc = value; self.state.pc = value;
self.port.start_request(self.is_supervisor(), self.state.pc, Size::Word, MemAccess::Read, MemType::Program, true)?; self.cycle.memory.start_request(self.is_supervisor(), self.state.pc, Size::Word, MemAccess::Read, MemType::Program, true)?;
Ok(()) Ok(())
} }

View File

@ -2,7 +2,7 @@
use femtos::Instant; use femtos::Instant;
use emulator_hal::bus::{BusType, BusAccess}; use emulator_hal::bus::{BusType, BusAccess};
use moa_core::{Error, Address, Addressable, BusPort}; use moa_core::{Address, Addressable, BusPort};
use crate::state::{M68k, M68kError, Exceptions}; use crate::state::{M68k, M68kError, Exceptions};
use crate::instructions::Size; use crate::instructions::Size;
@ -41,6 +41,7 @@ pub struct MemoryRequest {
pub code: FunctionCode, pub code: FunctionCode,
pub size: Size, pub size: Size,
pub address: u32, pub address: u32,
pub clock: Instant,
} }
impl FunctionCode { impl FunctionCode {
@ -69,11 +70,22 @@ impl Default for MemoryRequest {
code: FunctionCode::Reserved0, code: FunctionCode::Reserved0,
size: Size::Word, size: Size::Word,
address: 0, address: 0,
clock: Instant::START,
} }
} }
} }
impl MemoryRequest { impl MemoryRequest {
pub(crate) fn instruction(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, M68kError> {
self.i_n_bit = false;
self.code = FunctionCode::program(is_supervisor);
self.access = MemAccess::Read;
self.address = addr;
validate_address(addr)
}
#[inline]
pub fn get_type_code(&self) -> u16 { pub fn get_type_code(&self) -> u16 {
let ins = match self.i_n_bit { let ins = match self.i_n_bit {
false => 0x0000, false => 0x0000,
@ -89,9 +101,16 @@ impl MemoryRequest {
} }
} }
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct InstructionRequest {
pub request: MemoryRequest,
pub current_clock: Instant,
}
#[derive(Clone, Debug)]
pub struct M68kBusPort { pub struct M68kBusPort {
pub port: BusPort, //pub port: BusPort,
pub request: MemoryRequest, pub request: MemoryRequest,
pub cycle_start_clock: Instant, pub cycle_start_clock: Instant,
pub current_clock: Instant, pub current_clock: Instant,
@ -102,60 +121,52 @@ impl M68k {
// TODO should some of the ones from execute.rs move here // TODO should some of the ones from execute.rs move here
} }
impl M68kBusPort { impl Default for M68kBusPort {
pub fn new(port: BusPort) -> Self { fn default(/* port: BusPort */) -> Self {
Self { Self {
port, //port,
request: Default::default(), request: Default::default(),
cycle_start_clock: Instant::START, cycle_start_clock: Instant::START,
current_clock: Instant::START, current_clock: Instant::START,
} }
} }
}
pub fn data_width(&self) -> u8 { impl M68kBusPort {
self.port.data_width() pub fn new(clock: Instant) -> Self {
Self {
request: Default::default(),
cycle_start_clock: clock,
current_clock: clock,
}
} }
pub fn init_cycle(&mut self, clock: Instant) { pub(crate) fn read_data_sized(&mut self, port: &mut BusPort, is_supervisor: bool, addr: Address, size: Size) -> Result<u32, M68kError> {
self.cycle_start_clock = clock;
self.current_clock = clock;
}
pub(crate) fn read_instruction_word(&mut self, is_supervisor: bool, addr: u32) -> Result<u16, M68kError> {
self.start_instruction_request(is_supervisor, addr)?;
Ok(self.port.read_beu16(self.current_clock, addr as Address)?)
}
pub(crate) fn read_instruction_long(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, M68kError> {
self.start_instruction_request(is_supervisor, addr)?;
Ok(self.port.read_beu32(self.current_clock, addr as Address)?)
}
pub(crate) fn read_data_sized(&mut self, is_supervisor: bool, addr: Address, size: Size) -> Result<u32, M68kError> {
self.start_request(is_supervisor, addr as u32, size, MemAccess::Read, MemType::Data, false)?; self.start_request(is_supervisor, addr as u32, size, MemAccess::Read, MemType::Data, false)?;
Ok(match size { Ok(match size {
Size::Byte => self.port.read_u8(self.current_clock, addr).map(|value| value as u32), Size::Byte => port.read_u8(self.current_clock, addr).map(|value| value as u32),
Size::Word => self.port.read_beu16(self.current_clock, addr).map(|value| value as u32), Size::Word => port.read_beu16(self.current_clock, addr).map(|value| value as u32),
Size::Long => self.port.read_beu32(self.current_clock, addr), Size::Long => port.read_beu32(self.current_clock, addr),
}?) }?)
} }
pub(crate) fn write_data_sized(&mut self, is_supervisor: bool, addr: Address, value: u32, size: Size) -> Result<(), M68kError> { pub(crate) fn write_data_sized(&mut self, port: &mut BusPort, is_supervisor: bool, addr: Address, value: u32, size: Size) -> Result<(), M68kError> {
self.start_request(is_supervisor, addr as u32, size, MemAccess::Write, MemType::Data, false)?; self.start_request(is_supervisor, addr as u32, size, MemAccess::Write, MemType::Data, false)?;
Ok(match size { Ok(match size {
Size::Byte => self.port.write_u8(self.current_clock, addr, value as u8), Size::Byte => port.write_u8(self.current_clock, addr, value as u8),
Size::Word => self.port.write_beu16(self.current_clock, addr, value as u16), Size::Word => port.write_beu16(self.current_clock, addr, value as u16),
Size::Long => self.port.write_beu32(self.current_clock, addr, value), Size::Long => port.write_beu32(self.current_clock, addr, value),
}?) }?)
} }
pub(crate) fn start_instruction_request(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, M68kError> { pub(crate) fn read_instruction_word(&mut self, port: &mut BusPort, is_supervisor: bool, addr: u32) -> Result<u16, M68kError> {
self.request.i_n_bit = false; self.request.instruction(is_supervisor, addr)?;
self.request.code = FunctionCode::program(is_supervisor); Ok(port.read_beu16(self.current_clock, addr as Address)?)
self.request.access = MemAccess::Read; }
self.request.address = addr;
validate_address(addr) pub(crate) fn read_instruction_long(&mut self, port: &mut BusPort, is_supervisor: bool, addr: u32) -> Result<u32, M68kError> {
self.request.instruction(is_supervisor, addr)?;
Ok(port.read_beu32(self.current_clock, addr as Address)?)
} }
pub(crate) fn start_request(&mut self, is_supervisor: bool, addr: u32, size: Size, access: MemAccess, mtype: MemType, i_n_bit: bool) -> Result<u32, M68kError> { pub(crate) fn start_request(&mut self, is_supervisor: bool, addr: u32, size: Size, access: MemAccess, mtype: MemType, i_n_bit: bool) -> Result<u32, M68kError> {
@ -175,8 +186,8 @@ impl M68kBusPort {
} }
} }
pub(crate) fn dump_memory(&mut self, addr: u32, length: usize) { pub(crate) fn dump_memory(&mut self, port: &mut BusPort, addr: u32, length: usize) {
self.port.dump_memory(self.current_clock, addr as Address, length as u64); port.dump_memory(self.current_clock, addr as Address, length as u64);
} }
} }

View File

@ -5,25 +5,109 @@ use femtos::{Instant, Frequency};
use moa_core::{Address, Bus, BusPort}; use moa_core::{Address, Bus, BusPort};
use crate::decode::M68kDecoder;
use crate::debugger::M68kDebugger; use crate::debugger::M68kDebugger;
use crate::memory::M68kBusPort; use crate::memory::M68kBusPort;
use crate::timing::M68kInstructionTiming;
use crate::instructions::Target; use crate::instructions::Target;
use crate::execute::M68kCycle; use crate::execute::M68kCycle;
pub type ClockCycles = u16; pub type ClockCycles = u16;
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum M68kType { #[repr(u8)]
pub enum AddressWidth {
A32 = 32, // MC68020+
A24 = 24, // MC68000 64-Pin, MC68010
A22 = 22, // MC68008 52-Pin
A20 = 20, // MC68008 48-Pin
}
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u8)]
pub enum DataWidth {
D32 = 32,
D16 = 16,
D8 = 8,
}
/// The instruction set of the chip
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum CoreType {
MC68000, MC68000,
MC68010, MC68010,
MC68020, MC68020,
MC68030, MC68030,
} }
/// Complete collection of information about the CPU being simulated
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct CpuInfo {
pub chip: M68kType,
pub core_type: CoreType,
pub address_width: AddressWidth,
pub data_width: DataWidth,
pub frequency: Frequency,
}
/// The variant of the 68k family of CPUs that is being emulated
///
/// This can be used as a shorthand for creating a CpuInfo that
/// can be used by the simuation code to determine behaviour
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum M68kType {
MC68000,
MC68008,
MC68010,
MC68020,
MC68030,
}
impl From<M68kType> for CoreType {
fn from(cputype: M68kType) -> Self {
match cputype {
M68kType::MC68000 => CoreType::MC68000,
M68kType::MC68008 => CoreType::MC68000,
M68kType::MC68010 => CoreType::MC68010,
M68kType::MC68020 => CoreType::MC68020,
M68kType::MC68030 => CoreType::MC68030,
}
}
}
impl CpuInfo {
fn from(cputype: M68kType, frequency: Frequency) -> Self {
match cputype {
M68kType::MC68008 => Self {
chip: cputype,
core_type: cputype.into(),
address_width: AddressWidth::A22,
data_width: DataWidth::D8,
frequency,
},
M68kType::MC68000 | M68kType::MC68010 => Self {
chip: cputype,
core_type: cputype.into(),
address_width: AddressWidth::A24,
data_width: DataWidth::D16,
frequency,
},
M68kType::MC68020 | M68kType::MC68030 => Self {
chip: cputype,
core_type: cputype.into(),
address_width: AddressWidth::A32,
data_width: DataWidth::D32,
frequency,
}
}
}
}
const FLAGS_ON_RESET: u16 = 0x2700; const FLAGS_ON_RESET: u16 = 0x2700;
#[repr(u16)] #[repr(u16)]
@ -111,15 +195,11 @@ pub enum M68kError {
#[derive(Clone)] #[derive(Clone)]
pub struct M68k { pub struct M68k {
pub cputype: M68kType, pub info: CpuInfo,
pub frequency: Frequency,
pub state: M68kState, pub state: M68kState,
//pub decoder: M68kDecoder,
//pub timing: M68kInstructionTiming,
pub debugger: M68kDebugger, pub debugger: M68kDebugger,
pub port: M68kBusPort, pub port: BusPort,
//pub current_clock: Instant, pub cycle: Option<M68kCycle>,
pub cycle: M68kCycle,
} }
impl Default for M68kState { impl Default for M68kState {
@ -142,30 +222,20 @@ impl Default for M68kState {
} }
impl M68k { impl M68k {
pub fn new(cputype: M68kType, frequency: Frequency, port: BusPort) -> M68k { pub fn new(info: CpuInfo, port: BusPort) -> M68k {
let data_width = port.data_width();
M68k { M68k {
cputype, info,
frequency,
state: M68kState::default(), state: M68kState::default(),
//decoder: M68kDecoder::new(cputype, true, 0),
//timing: M68kInstructionTiming::new(cputype, port.data_width()),
debugger: M68kDebugger::default(), debugger: M68kDebugger::default(),
port: M68kBusPort::new(port), port,
//current_clock: Instant::START, cycle: None,
cycle: M68kCycle::default(cputype, data_width),
} }
} }
pub fn from_type(cputype: M68kType, frequency: Frequency, bus: Rc<RefCell<Bus>>, addr_offset: Address) -> Self { pub fn from_type(cputype: M68kType, frequency: Frequency, bus: Rc<RefCell<Bus>>, addr_offset: Address) -> Self {
match cputype { let info = CpuInfo::from(cputype, frequency);
M68kType::MC68000 | Self::new(info, BusPort::new(addr_offset, info.address_width as u8, info.data_width as u8, bus))
M68kType::MC68010 => Self::new(cputype, frequency, BusPort::new(addr_offset, 24, 16, bus)),
M68kType::MC68020 |
M68kType::MC68030 => Self::new(cputype, frequency, BusPort::new(addr_offset, 32, 32, bus)),
}
} }
} }
impl InterruptPriority { impl InterruptPriority {

View File

@ -255,7 +255,7 @@ mod execute_unit_tests {
use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Steppable, Device}; use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Steppable, Device};
use crate::{M68k, M68kType}; use crate::{M68k, M68kType};
use crate::execute::{Used, M68kCycle, M68kCycleGuard}; use crate::execute::{Used, M68kCycle, M68kCycleExecutor};
use crate::instructions::{Instruction, Target, Size}; use crate::instructions::{Instruction, Target, Size};
const INIT_STACK: Address = 0x00002000; const INIT_STACK: Address = 0x00002000;
@ -263,7 +263,7 @@ mod execute_unit_tests {
fn run_execute_test<F>(cputype: M68kType, mut test_func: F) fn run_execute_test<F>(cputype: M68kType, mut test_func: F)
where where
F: FnMut(M68kCycleGuard), F: FnMut(M68kCycleExecutor),
{ {
let mut system = System::default(); let mut system = System::default();
@ -277,13 +277,13 @@ mod execute_unit_tests {
let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10), system.bus.clone(), 0); let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10), system.bus.clone(), 0);
cpu.step(&system).unwrap(); cpu.step(&system).unwrap();
let mut cycle = M68kCycle::new(&mut cpu, system.clock); let mut cycle = M68kCycle::new(&mut cpu, system.clock);
let mut execution = cycle.begin(&mut cpu); let mut executor = cycle.begin(&mut cpu);
execution.cycle.decoder.init(true, execution.state.pc); executor.cycle.decoder.init(true, executor.state.pc);
assert_eq!(execution.state.pc, INIT_ADDR as u32); assert_eq!(executor.state.pc, INIT_ADDR as u32);
assert_eq!(execution.state.ssp, INIT_STACK as u32); assert_eq!(executor.state.ssp, INIT_STACK as u32);
assert_eq!(execution.cycle.decoder.instruction, Instruction::NOP); assert_eq!(executor.cycle.decoder.instruction, Instruction::NOP);
test_func(execution); test_func(executor);
} }
// //

View File

@ -5,7 +5,7 @@ use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Steppable, De
use moa_m68k::{M68k, M68kType}; use moa_m68k::{M68k, M68kType};
use moa_m68k::state::M68kState; use moa_m68k::state::M68kState;
use moa_m68k::execute::{M68kCycle, M68kCycleGuard}; use moa_m68k::execute::{M68kCycle, M68kCycleExecutor};
use moa_m68k::instructions::{Instruction, Target, Size, Sign, Direction, Condition}; use moa_m68k::instructions::{Instruction, Target, Size, Sign, Direction, Condition};
const INIT_STACK: Address = 0x00002000; const INIT_STACK: Address = 0x00002000;
@ -37,7 +37,7 @@ struct TestCase {
fn run_execute_test<F>(cputype: M68kType, mut test_func: F) fn run_execute_test<F>(cputype: M68kType, mut test_func: F)
where where
F: FnMut(M68kCycleGuard, System), F: FnMut(M68kCycleExecutor, System),
{ {
let mut system = System::default(); let mut system = System::default();

View File

@ -1,4 +1,10 @@
* I want to push System, and BusPort into only the step function
* first I need to make Decoder take &mut Addressable, and still function like it does
* next I need to make Executor only access through a &mut Addressable
* move the interrupt controller logic to the step() function only, and have a customish interrupt interface into the sim
* move the impls for Step, Transmutable, etc into a moa.rs file or something
* the remaining code should really use Addressable, and then we can swap it for BusAccess
* 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 * 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 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