From e558fc01bfb53135406933c9b14718b960e60043 Mon Sep 17 00:00:00 2001 From: transistor Date: Mon, 11 Oct 2021 15:16:04 -0700 Subject: [PATCH] Refactored and fixed some warnings --- src/cpus/m68k/debugger.rs | 2 +- src/cpus/m68k/decode.rs | 84 ++++++++++++++++++++++++++------------ src/cpus/m68k/execute.rs | 37 ++++++++--------- src/cpus/m68k/state.rs | 21 ++++++++-- src/peripherals/ata.rs | 10 ++++- src/peripherals/mc68681.rs | 39 ++++++++++++++++-- 6 files changed, 137 insertions(+), 56 deletions(-) diff --git a/src/cpus/m68k/debugger.rs b/src/cpus/m68k/debugger.rs index e49afb4..d7b7d87 100644 --- a/src/cpus/m68k/debugger.rs +++ b/src/cpus/m68k/debugger.rs @@ -124,7 +124,7 @@ impl M68k { }, "dis" | "disassemble" => { let mut decoder = M68kDecoder::new(self.cputype, 0, 0); - decoder.dump_disassembly(system, self.state.pc, 0x1000); + //decoder.dump_disassembly(system, self.state.pc, 0x1000); }, "so" | "stepout" => { self.debugger.step_until_return = Some(self.debugger.stack_tracer.calls.len() - 1); diff --git a/src/cpus/m68k/decode.rs b/src/cpus/m68k/decode.rs index d202d47..239cea1 100644 --- a/src/cpus/m68k/decode.rs +++ b/src/cpus/m68k/decode.rs @@ -3,10 +3,10 @@ use std::fmt; use crate::error::Error; use crate::system::System; -use crate::memory::Address; +use crate::memory::{Address, Addressable}; use crate::devices::AddressableDeviceRefMut; -use super::state::{M68kType, ERR_ILLEGAL_INSTRUCTION}; +use super::state::{M68kType, Exceptions}; const OPCG_BIT_OPS: u8 = 0x0; @@ -19,11 +19,14 @@ const OPCG_BRANCH: u8 = 0x6; const OPCG_MOVEQ: u8 = 0x7; const OPCG_DIV_OR: u8 = 0x8; const OPCG_SUB: u8 = 0x9; -const OPCG_RESERVED1: u8 = 0xA; const OPCG_CMP_EOR: u8 = 0xB; const OPCG_MUL_AND: u8 = 0xC; const OPCG_ADD: u8 = 0xD; const OPCG_SHIFT: u8 = 0xE; + +#[allow(dead_code)] +const OPCG_RESERVED1: u8 = 0xA; +#[allow(dead_code)] const OPCG_RESERVED2: u8 = 0xF; @@ -236,7 +239,7 @@ impl M68kDecoder { 0b0000 => Ok(Instruction::ORtoCCR(data as u8)), 0b0001 => Ok(Instruction::ANDtoCCR(data as u8)), 0b1010 => Ok(Instruction::EORtoCCR(data as u8)), - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } }, 0b01 => { @@ -245,10 +248,10 @@ impl M68kDecoder { 0b0000 => Ok(Instruction::ORtoSR(data)), 0b0010 => Ok(Instruction::ANDtoSR(data)), 0b1010 => Ok(Instruction::EORtoSR(data)), - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } }, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } else if (ins & 0x138) == 0x108 { let dreg = get_high_reg(ins); @@ -275,7 +278,7 @@ impl M68kDecoder { 0b01 => Ok(Instruction::BCHG(bitnum, target, size)), 0b10 => Ok(Instruction::BCLR(bitnum, target, size)), 0b11 => Ok(Instruction::BSET(bitnum, target, size)), - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } else { let size = get_size(ins); @@ -283,7 +286,7 @@ impl M68kDecoder { Some(Size::Byte) => (self.read_instruction_word(system)? as u32 & 0xFF), Some(Size::Word) => self.read_instruction_word(system)? as u32, Some(Size::Long) => self.read_instruction_long(system)?, - None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), }; let target = self.decode_lower_effective_address(system, ins, size)?; @@ -294,7 +297,7 @@ impl M68kDecoder { 0b0110 => Ok(Instruction::ADD(Target::Immediate(data), target, size.unwrap())), 0b1010 => Ok(Instruction::EOR(Target::Immediate(data), target, size.unwrap())), 0b1100 => Ok(Instruction::CMP(Target::Immediate(data), target, size.unwrap())), - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } }, @@ -330,7 +333,7 @@ impl M68kDecoder { let size = match get_size(ins) { Some(Size::Word) => Size::Word, Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), }; let reg = get_high_reg(ins); @@ -362,7 +365,7 @@ impl M68kDecoder { match get_size(ins) { Some(size) => Ok(Instruction::CLR(target, size)), None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)), - None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } }, 0b100 => { @@ -377,7 +380,7 @@ impl M68kDecoder { None => Ok(Instruction::MOVEtoSR(target)), } }, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } else if ins_0f00 == 0x800 { let subselect = (ins & 0x01C0) >> 6; @@ -402,7 +405,7 @@ impl M68kDecoder { let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; Ok(Instruction::EXT(get_low_reg(ins), size)) }, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } else if ins_0f00 == 0xA00 { if (ins & 0x0FF) == 0xFC { @@ -461,15 +464,15 @@ impl M68kDecoder { }; let creg = match ins2 & 0xFFF { 0x801 => ControlRegister::VBR, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), }; Ok(Instruction::MOVEC(target, creg, dir)) }, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } } else { - return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)); + return Err(Error::processor(Exceptions::IllegalInstruction as u32)); } }, OPCG_ADDQ_SUBQ => { @@ -518,7 +521,7 @@ impl M68kDecoder { }, OPCG_MOVEQ => { if (ins & 0x0100) != 0 { - return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)); + return Err(Error::processor(Exceptions::IllegalInstruction as u32)); } let reg = get_high_reg(ins); let data = (ins & 0xFF) as u8; @@ -596,7 +599,7 @@ impl M68kDecoder { let target = self.decode_lower_effective_address(system, ins, Some(size))?; Ok(Instruction::CMPA(target, reg, size)) }, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } }, OPCG_MUL_AND => { @@ -617,7 +620,7 @@ impl M68kDecoder { 0b01000 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectDReg(regy))), 0b01001 => Ok(Instruction::EXG(Target::DirectAReg(regx), Target::DirectAReg(regy))), 0b10001 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectAReg(regy))), - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } else if size.is_none() { let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed }; @@ -675,7 +678,7 @@ impl M68kDecoder { 0b01 => Ok(Instruction::LSd(count, Target::DirectDReg(reg), size, dir)), 0b10 => Ok(Instruction::ROXd(count, Target::DirectDReg(reg), size, dir)), 0b11 => Ok(Instruction::ROd(count, Target::DirectDReg(reg), size, dir)), - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } }, None => { @@ -687,12 +690,12 @@ impl M68kDecoder { 0b01 => Ok(Instruction::LSd(count, target, Size::Word, dir)), 0b10 => Ok(Instruction::ROXd(count, target, Size::Word, dir)), 0b11 => Ok(Instruction::ROd(count, target, Size::Word, dir)), - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } }, } }, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } @@ -742,7 +745,7 @@ impl M68kDecoder { panic!("Not Implemented"); } else { - Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)) + Err(Error::processor(Exceptions::IllegalInstruction as u32)) } } @@ -781,18 +784,47 @@ impl M68kDecoder { let data = match size { Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(system)? as u32, Some(Size::Long) => self.read_instruction_long(system)?, - None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), }; Target::Immediate(data) }, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } }, - _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), }; Ok(value) } + pub fn dump_disassembly(&mut self, system: &System, start: u32, length: u32) { + let mut next = start; + while next < (start + length) { + match self.decode_at(&system, next) { + Ok(()) => { + self.dump_decoded(system); + next = self.end; + }, + Err(err) => { + println!("{:?}", err); + match err { + Error { native, .. } if native == Exceptions::IllegalInstruction as u32 => { + println!(" at {:08x}: {:04x}", self.start, system.get_bus().read_beu16(self.start as Address).unwrap()); + }, + _ => { }, + } + return; + }, + } + } + } + + pub fn dump_decoded(&mut self, system: &System) { + let ins_data: Result = + (0..((self.end - self.start) / 2)).map(|offset| + Ok(format!("{:04x} ", system.get_bus().read_beu16((self.start + (offset * 2)) as Address).unwrap())) + ).collect(); + debug!("{:#010x}: {}\n\t{:?}\n", self.start, ins_data.unwrap(), self.instruction); + } } #[inline(always)] diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 40b1a0d..7d43957 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -5,7 +5,6 @@ use crate::memory::{Address, Addressable}; use crate::devices::{Clock, Steppable, Interruptable}; use super::decode::{ - M68kDecoder, Instruction, Target, Size, @@ -18,7 +17,7 @@ use super::decode::{ sign_extend_to_long }; -use super::state::{M68k, Status, Flags, InterruptPriority}; +use super::state::{M68k, Status, Flags, Exceptions, InterruptPriority}; impl Steppable for M68k { fn step(&mut self, system: &System) -> Result { @@ -50,24 +49,15 @@ impl Interruptable for M68k { } impl M68k { + #[allow(dead_code)] pub fn is_running(&self) -> bool { self.state.status != Status::Stopped } - pub fn init(&mut self, system: &System) -> Result<(), Error> { - println!("Initializing CPU"); - - self.state.msp = system.get_bus().read_beu32(0)?; - self.state.pc = system.get_bus().read_beu32(4)?; - self.state.status = Status::Running; - - Ok(()) - } - pub fn step_internal(&mut self, system: &System) -> Result<(), Error> { match self.state.status { Status::Init => self.init(system), - Status::Stopped | Status::Halted => Err(Error::new("CPU stopped")), + Status::Stopped => Err(Error::new("CPU stopped")), Status::Running => { let timer = self.timer.cycle.start(); self.decode_next(system)?; @@ -85,6 +75,13 @@ impl M68k { } } + pub fn init(&mut self, system: &System) -> Result<(), Error> { + self.state.msp = system.get_bus().read_beu32(0)?; + self.state.pc = system.get_bus().read_beu32(4)?; + self.state.status = Status::Running; + Ok(()) + } + pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), Error> { let current_ipl = self.state.current_ipl as u8; let pending_ipl = self.state.pending_ipl as u8; @@ -126,12 +123,7 @@ impl M68k { self.timer.decode.end(timer); if self.debugger.use_tracing { - // Print instruction bytes for debugging - let ins_data: Result = - (0..((self.decoder.end - self.decoder.start) / 2)).map(|offset| - Ok(format!("{:04x} ", system.get_bus().read_beu16((self.decoder.start + (offset * 2)) as Address)?)) - ).collect(); - debug!("{:#010x}: {}\n\t{:?}\n", self.decoder.start, ins_data?, self.decoder.instruction); + self.decoder.dump_decoded(system); } if self.debugger.use_debugger { @@ -259,6 +251,11 @@ impl M68k { } let value = self.get_target_value(system, src, size)?; + if value == 0 { + self.exception(system, Exceptions::ZeroDivide as u8)?; + return Ok(()); + } + let existing = self.get_target_value(system, dest, Size::Long)?; let result = match sign { Sign::Signed => { @@ -537,7 +534,7 @@ impl M68k { }, Instruction::TRAPV => { if self.get_flag(Flags::Overflow) { - self.exception(system, 7)?; + self.exception(system, Exceptions::TrapvInstruction as u8)?; } }, Instruction::UNLK(reg) => { diff --git a/src/cpus/m68k/state.rs b/src/cpus/m68k/state.rs index 5e54129..8cb64bf 100644 --- a/src/cpus/m68k/state.rs +++ b/src/cpus/m68k/state.rs @@ -9,9 +9,13 @@ use super::debugger::M68kDebugger; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum M68kType { + #[allow(dead_code)] MC68000, + #[allow(dead_code)] MC68010, + #[allow(dead_code)] MC68020, + #[allow(dead_code)] MC68030, } @@ -31,9 +35,17 @@ pub enum Flags { Tracing = 0x8000, } -pub const ERR_BUS_ERROR: u32 = 2; -pub const ERR_ADDRESS_ERROR: u32 = 3; -pub const ERR_ILLEGAL_INSTRUCTION: u32 = 4; +#[repr(u8)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Exceptions { + BusError = 2, + AddressError = 3, + IllegalInstruction = 4, + ZeroDivide = 5, + ChkInstruction = 6, + TrapvInstruction = 7, + PrivilegeViolation = 8, +} #[derive(Copy, Clone, Debug, PartialEq)] @@ -41,7 +53,6 @@ pub enum Status { Init, Running, Stopped, - Halted, } #[repr(u8)] @@ -72,6 +83,7 @@ impl InterruptPriority { } } +#[derive(Clone, Debug, PartialEq)] pub struct M68kState { pub status: Status, pub current_ipl: InterruptPriority, @@ -127,6 +139,7 @@ impl M68k { } } + #[allow(dead_code)] pub fn reset(&mut self) { self.state = M68kState::new(); self.decoder = M68kDecoder::new(self.cputype, 0, 0); diff --git a/src/peripherals/ata.rs b/src/peripherals/ata.rs index 40bd314..6f4d085 100644 --- a/src/peripherals/ata.rs +++ b/src/peripherals/ata.rs @@ -7,8 +7,6 @@ use crate::memory::{Address, Addressable}; use crate::devices::{Clock, Steppable}; -const ATA_REG_DEV_CONTROL: Address = 0x1D; -const ATA_REG_DEV_ADDRESS: Address = 0x1F; const ATA_REG_DATA_WORD: Address = 0x20; const ATA_REG_DATA_BYTE: Address = 0x21; const ATA_REG_FEATURE: Address = 0x23; @@ -26,8 +24,11 @@ const ATA_CMD_WRITE_SECTORS: u8 = 0x30; const ATA_CMD_IDENTIFY: u8 = 0xEC; const ATA_CMD_SET_FEATURE: u8 = 0xEF; +#[allow(dead_code)] const ATA_ST_BUSY: u8 = 0x80; +#[allow(dead_code)] const ATA_ST_DATA_READY: u8 = 0x08; +#[allow(dead_code)] const ATA_ST_ERROR: u8 = 0x01; const ATA_SECTOR_SIZE: u32 = 512; @@ -37,6 +38,7 @@ const DEV_NAME: &'static str = "ata"; pub struct AtaDevice { pub selected_sector: u32, pub selected_count: u32, + pub last_error: u8, pub contents: Vec, } @@ -46,6 +48,7 @@ impl AtaDevice { AtaDevice { selected_sector: 0, selected_count: 0, + last_error: 0, contents: vec![], } } @@ -92,6 +95,9 @@ impl Addressable for AtaDevice { ATA_REG_STATUS => { data[0] = ATA_ST_DATA_READY; }, + ATA_REG_ERROR => { + data[0] = self.last_error; + }, _ => { println!("{}: reading from {:0x}", DEV_NAME, addr); }, } diff --git a/src/peripherals/mc68681.rs b/src/peripherals/mc68681.rs index 48e236a..5fec59c 100644 --- a/src/peripherals/mc68681.rs +++ b/src/peripherals/mc68681.rs @@ -45,13 +45,21 @@ const REG_IVR_WR: Address = 0x19; // Status Register Bits (SRA/SRB) +#[allow(dead_code)] const SR_RECEIVED_BREAK: u8 = 0x80; +#[allow(dead_code)] const SR_FRAMING_ERROR: u8 = 0x40; +#[allow(dead_code)] const SR_PARITY_ERROR: u8 = 0x20; +#[allow(dead_code)] const SR_OVERRUN_ERROR: u8 = 0x10; +#[allow(dead_code)] const SR_TX_EMPTY: u8 = 0x08; +#[allow(dead_code)] const SR_TX_READY: u8 = 0x04; +#[allow(dead_code)] const SR_RX_FULL: u8 = 0x02; +#[allow(dead_code)] const SR_RX_READY: u8 = 0x01; @@ -160,6 +168,11 @@ pub struct MC68681 { pub timer_preload: u16, pub timer_count: u16, pub is_timing: bool, + + pub input_pin_change: u8, + pub input_state: u8, + pub output_conf: u8, + pub output_state: u8, } impl MC68681 { @@ -176,6 +189,11 @@ impl MC68681 { timer_preload: 0, timer_count: 0, is_timing: true, + + input_pin_change: 0, + input_state: 0, + output_conf: 0, + output_state: 0, } } @@ -247,6 +265,12 @@ impl Addressable for MC68681 { REG_ISR_RD => { data[0] = self.int_status; }, + REG_IPCR_RD => { + data[0] = self.input_pin_change; + }, + REG_INPUT_RD => { + data[0] = self.input_state; + }, REG_START_RD => { self.timer_count = self.timer_preload; self.is_timing = true; @@ -271,9 +295,9 @@ impl Addressable for MC68681 { fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { println!("{}: writing {:0x} to {:0x}", DEV_NAME, data[0], addr); match addr { - //REG_MR1A_MR2A | REG_ACR_WR => { - // // TODO config - //}, + REG_MR1A_MR2A | REG_MR1B_MR2B | REG_CSRA_WR | REG_CSRB_WR => { + // NOTE we aren't simulating the serial speeds, so we aren't doing anything with these settings atm + }, REG_ACR_WR => { self.acr = data[0]; } @@ -309,6 +333,15 @@ impl Addressable for MC68681 { REG_IVR_WR => { self.int_vector = data[0]; }, + REG_OPCR_WR => { + self.output_conf = data[0]; + }, + REG_OUT_SET => { + self.output_state |= data[0]; + }, + REG_OUT_RESET => { + self.output_state &= !data[0]; + }, _ => { }, } Ok(())