diff --git a/src/disas.rs b/src/disas.rs index 6cf5a0e..11813f8 100644 --- a/src/disas.rs +++ b/src/disas.rs @@ -4,7 +4,7 @@ use bitvec::prelude::*; use crate::instruction::{ BitInsType, Condition, EffectiveAddress, Instruction, MoveDirection, RegisterEffective, - Rotation, ShiftDirection, ShiftType, Size, + Rotation, ShiftDirection, ShiftType, Size, ControlRegister, }; use derive_try_from_primitive::TryFromPrimitive; @@ -488,6 +488,22 @@ impl Disasm<'_, T> { Ok(Instruction::Trapv) } else if ins_word[4..16].load_be::() == 0b1110_0111_0111 { Ok(Instruction::Rtr) + } else if ins_word[4..15].load_be::() == 0b111_0011_1101 { + let dir = if ins_word[15] { + MoveDirection::RegToMem + } else { + MoveDirection::MemToReg + }; + let word2 = self.read_prog_word()?; + let word2 = word2.view_bits::(); + let reg_num = word2[1..4].load_be::(); + let ea = if word2[0] { + EffectiveAddress::AddressReg(reg_num) + } else { + EffectiveAddress::DataReg(reg_num) + }; + let ctrl = ControlRegister::try_from(word2[4..16].load_be::()).map_err(|_| DisassemblyError::InvalidInstruction)?; + Ok(Instruction::Movec(dir, ea, ctrl)) } else if ins_word[4..10].load_be::() == 0b11_1010 { let dst_mode = AddressingMode::try_from(ins_word[10..13].load_be::()).unwrap(); diff --git a/src/instruction.rs b/src/instruction.rs index 8b0a972..2516741 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -265,6 +265,27 @@ impl Display for ShiftDirection { } } + +#[derive(Debug, Clone, TryFromPrimitive)] +#[repr(u16)] +pub enum ControlRegister { + SFC = 0x0, + DFC = 0x1, + USP = 0x800, + VBR = 0x801, +} + +impl Display for ControlRegister { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::SFC => f.write_str("SFC"), + Self::DFC => f.write_str("DFC"), + Self::USP => f.write_str("USP"), + Self::VBR => f.write_str("VBR"), + } + } +} + #[derive(Debug, Clone)] pub enum Instruction { OriCcr(u8), @@ -324,6 +345,7 @@ pub enum Instruction { Rts, Trapv, Rtr, + Movec(MoveDirection, EffectiveAddress, ControlRegister), Jsr(EffectiveAddress), Jmp(EffectiveAddress), Movem(MoveDirection, Size, EffectiveAddress, Vec), @@ -466,6 +488,12 @@ impl Display for Instruction { Self::Rts => write!(f, "RTS"), Self::Trapv => write!(f, "TRAPV"), Self::Rtr => write!(f, "RTR"), + Self::Movec(dir, ea, ctrl) => { + match dir { + MoveDirection::MemToReg => write!(f, "MOVEC {ctrl}, {ea}"), + MoveDirection::RegToMem => write!(f, "MOVEC {ea}, {ctrl}"), + } + } Self::Jsr(ea) => write!(f, "JSR {ea}"), Self::Jmp(ea) => write!(f, "JMP {ea}"), Self::Movem(dir, size, dst, regs) => { diff --git a/src/m68k.rs b/src/m68k.rs index 2117189..9c9ea28 100644 --- a/src/m68k.rs +++ b/src/m68k.rs @@ -9,7 +9,7 @@ use crate::{ disas::{self, DisassemblyError}, instruction::{ ArithType, BitInsType, EffectiveAddress, Instruction, MoveDirection, ShiftDirection, - ShiftType, Size, + ShiftType, Size, ControlRegister, }, }; @@ -128,6 +128,7 @@ pub struct M68K { aregs: [u32; 7], usp: u32, ssp: u32, + vbr: u32, pc: u32, sr: u16, bus: Backplane, @@ -179,6 +180,7 @@ impl M68K { aregs: [0; 7], usp: 0, ssp: 0, + vbr: 0, pc: 0, sr: 0, bus, @@ -199,6 +201,7 @@ impl M68K { self.read_word(6), ) { self.ssp = ((ssp_high as u32) << 16) | (ssp_low as u32); + self.vbr = 0; self.pc = (u32::from(pc_high) << 16) | u32::from(pc_low); self.sr = 0x2700 | self.sr & 0xFF; self.stopped = false; @@ -675,6 +678,34 @@ impl M68K { self.sr = (self.sr & 0xFF00) | u16::from(self.pop(Size::Word)? as u8); self.pc = self.pop(Size::Long)?; } + Instruction::Movec(dir, ea, ctrl) => { + match dir { + MoveDirection::MemToReg => { + match ctrl { + ControlRegister::SFC => todo!(), + ControlRegister::DFC => todo!(), + ControlRegister::USP => { + self.write_effective(ea, self.usp, Size::Long)?; + }, + ControlRegister::VBR => { + self.write_effective(ea, self.vbr, Size::Long)?; + }, + } + }, + MoveDirection::RegToMem => { + match ctrl { + ControlRegister::SFC => todo!(), + ControlRegister::DFC => todo!(), + ControlRegister::USP => { + self.usp = self.read_effective(ea, Size::Long)?; + }, + ControlRegister::VBR => { + self.vbr = self.read_effective(ea, Size::Long)? &!(0x3FF); + }, + } + }, + } + } Instruction::Jsr(ea) => { self.push(self.pc, Size::Long)?; self.pc = self.effective_address(ea)?; @@ -1621,7 +1652,7 @@ impl M68K { } fn trap(&mut self, vector: u8) -> Result<(), DetailedBusError> { - let new_pc = self.read_address(u32::from(vector) * 4, Size::Long)?; + let new_pc = self.read_address((u32::from(vector) * 4) + self.vbr, Size::Long)?; self.push(u32::from(vector), Size::Word)?; self.push(self.pc, Size::Long)?; self.push(u32::from(self.sr), Size::Word)?; @@ -1638,7 +1669,7 @@ impl M68K { fault_addr: u32, write_data: u16, ) -> Result<(), DetailedBusError> { - let new_pc = self.read_address(2 * 4, Size::Long)?; + let new_pc = self.read_address(2 * 4 + self.vbr, Size::Long)?; // Version & internal information self.push(0, Size::Long)?; self.push(0, Size::Long)?;