From 24e050a840c84abbdf779a982455f0d7939f7c75 Mon Sep 17 00:00:00 2001 From: transistor Date: Sat, 16 Oct 2021 10:01:14 -0700 Subject: [PATCH] Added supervisor checks --- src/cpus/m68k/execute.rs | 56 ++++++++++++++++++++++++++++++---------- todo.txt | 11 ++++---- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index c448fcc..2895b02 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -1,6 +1,6 @@ -use crate::error::Error; use crate::system::System; +use crate::error::{ErrorType, Error}; use crate::memory::{Address, Addressable}; use crate::devices::{Clock, Steppable, Interruptable}; @@ -65,18 +65,14 @@ impl M68k { Status::Init => self.init(system), Status::Stopped => Err(Error::new("CPU stopped")), Status::Running => { - let timer = self.timer.cycle.start(); - self.decode_next(system)?; - self.execute_current(system)?; - self.timer.cycle.end(timer); - - //if (self.timer.cycle.events % 500) == 0 { - // println!("{}", self.timer); - //} - - self.check_pending_interrupts(system)?; - - Ok(()) + match self.cycle_one(system) { + Ok(()) => Ok(()), + Err(Error { err: ErrorType::Processor, native, .. }) => { + self.exception(system, native as u8)?; + Ok(()) + }, + Err(err) => Err(err), + } }, } } @@ -88,6 +84,20 @@ impl M68k { Ok(()) } + pub fn cycle_one(&mut self, system: &System) -> Result<(), Error> { + let timer = self.timer.cycle.start(); + self.decode_next(system)?; + self.execute_current(system)?; + self.timer.cycle.end(timer); + + //if (self.timer.cycle.events % 500) == 0 { + // println!("{}", self.timer); + //} + + self.check_pending_interrupts(system)?; + 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; @@ -167,6 +177,7 @@ impl M68k { self.state.sr = self.state.sr & (value as u16); }, Instruction::ANDtoSR(value) => { + self.require_supervisor()?; self.state.sr = self.state.sr & value; }, Instruction::ASd(count, target, size, shift_dir) => { @@ -286,6 +297,7 @@ impl M68k { self.state.sr = self.state.sr ^ (value as u16); }, Instruction::EORtoSR(value) => { + self.require_supervisor()?; self.state.sr = self.state.sr ^ value; }, //Instruction::EXG(Target, Target) => { @@ -350,9 +362,11 @@ impl M68k { *addr = value; }, Instruction::MOVEfromSR(target) => { + self.require_supervisor()?; self.set_target_value(system, target, self.state.sr as u32, Size::Word)?; }, Instruction::MOVEtoSR(target) => { + self.require_supervisor()?; self.state.sr = self.get_target_value(system, target, Size::Word)? as u16; }, Instruction::MOVEtoCCR(target) => { @@ -360,6 +374,7 @@ impl M68k { self.state.sr = (self.state.sr & 0xFF00) | (value & 0x00FF); }, Instruction::MOVEC(target, control_reg, dir) => { + self.require_supervisor()?; match dir { Direction::FromTarget => { let value = self.get_target_value(system, target, Size::Long)?; @@ -374,6 +389,7 @@ impl M68k { } }, Instruction::MOVEUSP(target, dir) => { + self.require_supervisor()?; match dir { Direction::ToTarget => self.set_target_value(system, target, self.state.usp, Size::Long)?, Direction::FromTarget => { self.state.usp = self.get_target_value(system, target, Size::Long)?; }, @@ -474,6 +490,7 @@ impl M68k { self.state.sr = self.state.sr | (value as u16); }, Instruction::ORtoSR(value) => { + self.require_supervisor()?; self.state.sr = self.state.sr | value; }, Instruction::PEA(target) => { @@ -481,6 +498,7 @@ impl M68k { self.push_long(system, value)?; }, //Instruction::RESET => { + // self.require_supervisor()?; //}, Instruction::ROd(count, target, size, shift_dir) => { let count = self.get_target_value(system, count, size)? % 64; @@ -497,6 +515,7 @@ impl M68k { //Instruction::ROXd(Target, Target, Size, ShiftDirection) => { //}, Instruction::RTE => { + self.require_supervisor()?; self.state.sr = self.pop_word(system)?; self.state.pc = self.pop_long(system)?; let _ = self.pop_word(system)?; @@ -516,6 +535,7 @@ impl M68k { } }, Instruction::STOP(flags) => { + self.require_supervisor()?; self.state.sr = flags; self.state.status = Status::Stopped; }, @@ -718,10 +738,20 @@ impl M68k { } } + #[inline(always)] fn is_supervisor(&self) -> bool { self.state.sr & (Flags:: Supervisor as u16) != 0 } + #[inline(always)] + fn require_supervisor(&self) -> Result<(), Error> { + if self.is_supervisor() { + Ok(()) + } else { + Err(Error::processor(Exceptions::PrivilegeViolation as u32)) + } + } + #[inline(always)] fn get_flag(&self, flag: Flags) -> bool { (self.state.sr & (flag as u16)) != 0 diff --git a/todo.txt b/todo.txt index ec18798..73616c5 100644 --- a/todo.txt +++ b/todo.txt @@ -1,14 +1,15 @@ -* add exception for privileged instructions. Should you separate them in the `match` or just put a guard into the instructions, and if the latter, can - you use the emulator's errors to surface the execption up to the `step_internal` function but not to `System`? +* make IO in mc68681 use a separate thread... will that improve performance of mc68681.step()? -* make it possible to break out of the current execution, into the debugger -* how can you add 68030 support? Should it be all one module that checks maybe during decode if the instruction is supported? Should it 'inherit' from the MC68010 object +* make it possible to break out of the current execution, into the debugger, by using a certain keystroke +* add support for MC68020+ indexing modes +* add support for MMU +* add support for FPU * make tests for each instruction * unimplemented: ABCD, ADDX, BKPT, CHK, EXG, ILLEGAL, MOVEfromCCR, MOVEP, RTR, RTD, SBCD, SUBX * undecoded: ADDX, SUBX -* modify execution for >=MC68020: DIVSL, DIVUL, EXTB, LINK, MOVEM, MULSL, MULUL, RTM, TRAPcc, UNPK +* modify execution for >=MC68020: DIVSL, DIVUL, LINK, MOVEM, MULSL, MULUL, RTM, TRAPcc, UNPK * implement the full extension word for MC68020+ * >=MC68020 instructions: BFCHG, BFCLR, BFEXTS, BFEXTU, BFFFO, BFINS, BFSET, BFTST, CALLM, CAS, CAS2, CHK2, CMP2, PACK