Added interrupt triggering from mc68681

This commit is contained in:
transistor 2021-10-07 13:57:50 -07:00
parent 7bd7f3e64f
commit ecbaf6a68b
5 changed files with 59 additions and 5 deletions

View File

@ -31,8 +31,9 @@ impl Steppable for MC68010 {
} }
impl Interruptable for MC68010 { impl Interruptable for MC68010 {
fn handle_interrupt(&mut self, system: &System, number: u8) -> Result<(), Error> { fn handle_interrupt(&mut self, _system: &System, number: u8) -> Result<(), Error> {
self.exception(system, number) self.state.status = Status::PendingExecption(number);
Ok(())
} }
} }
@ -67,10 +68,16 @@ impl MC68010 {
Ok(()) Ok(())
}, },
Status::PendingExecption(num) => {
self.exception(system, num)?;
self.state.status = Status::Running;
Ok(())
}
} }
} }
pub fn exception(&mut self, system: &System, number: u8) -> Result<(), Error> { pub fn exception(&mut self, system: &System, number: u8) -> Result<(), Error> {
println!("raising exeception {:x}", number);
let offset = (number as u16) << 2; let offset = (number as u16) << 2;
self.push_word(system, offset)?; self.push_word(system, offset)?;
self.push_long(system, self.state.pc)?; self.push_long(system, self.state.pc)?;

View File

@ -29,6 +29,7 @@ pub const ERR_ILLEGAL_INSTRUCTION: u32 = 4;
pub enum Status { pub enum Status {
Init, Init,
Running, Running,
PendingExecption(u8),
Stopped, Stopped,
Halted, Halted,
} }

View File

@ -41,7 +41,7 @@ fn main() {
//cpu.add_breakpoint(0x0c94); //cpu.add_breakpoint(0x0c94);
//cpu.add_breakpoint(0x103234); //cpu.add_breakpoint(0x103234);
//cpu.add_breakpoint(0x224); //cpu.add_breakpoint(0x224);
//cpu.add_breakpoint(0x100334); //cpu.add_breakpoint(0x106ed2);
system.add_interruptable_device(wrap_interruptable(cpu)).unwrap(); system.add_interruptable_device(wrap_interruptable(cpu)).unwrap();
loop { loop {

View File

@ -48,13 +48,27 @@ const SR_RX_FULL: u8 = 0x02;
const SR_RX_READY: u8 = 0x01; const SR_RX_READY: u8 = 0x01;
// Interrupt Status/Mask Bits (ISR/IVR)
const ISR_INPUT_CHANGE: u8 = 0x80;
const ISR_CH_B_BREAK_CHANGE: u8 = 0x40;
const ISR_CH_B_RX_READY_FULL: u8 = 0x20;
const ISR_CH_B_TX_READY: u8 = 0x10;
const ISR_TIMER_CHANGE: u8 = 0x08;
const ISR_CH_A_BREAK_CHANGE: u8 = 0x04;
const ISR_CH_A_RX_READY_FULL: u8 = 0x02;
const ISR_CH_A_TX_READY: u8 = 0x01;
const DEV_NAME: &'static str = "mc68681"; const DEV_NAME: &'static str = "mc68681";
pub struct MC68681 { pub struct MC68681 {
pub tty: Option<PtyMaster>, pub tty: Option<PtyMaster>,
pub status: u8, pub status: u8,
pub input: u8, pub input: u8,
pub int_mask: u8,
pub int_status: u8,
pub int_vector: u8, pub int_vector: u8,
pub int_edge_trigger: u8,
pub timer: u16, pub timer: u16,
} }
@ -64,7 +78,10 @@ impl MC68681 {
tty: None, tty: None,
status: 0x0C, status: 0x0C,
input: 0, input: 0,
int_mask: 0,
int_status: 0,
int_vector: 0, int_vector: 0,
int_edge_trigger: 0,
timer: 0, timer: 0,
} }
} }
@ -89,7 +106,7 @@ impl MC68681 {
} }
} }
pub fn step_internal(&mut self, _system: &System) -> Result<(), Error> { pub fn step_internal(&mut self, system: &System) -> Result<(), Error> {
if !self.rx_ready() && self.tty.is_some() { if !self.rx_ready() && self.tty.is_some() {
let mut buf = [0; 1]; let mut buf = [0; 1];
let tty = self.tty.as_mut().unwrap(); let tty = self.tty.as_mut().unwrap();
@ -106,6 +123,17 @@ impl MC68681 {
} }
} }
// TODO this is a hack
if (system.clock % 10000) == 0 {
self.int_status |= ISR_TIMER_CHANGE;
self.int_edge_trigger = self.int_status;
}
if (self.int_edge_trigger & self.int_mask) != 0 {
system.trigger_interrupt(self.int_vector)?;
self.int_edge_trigger = 0;
}
Ok(()) Ok(())
} }
@ -133,6 +161,10 @@ impl Addressable for MC68681 {
data[0] = self.input; data[0] = self.input;
self.status &= !SR_RX_READY; self.status &= !SR_RX_READY;
}, },
REG_ISR_RD => {
data[0] = self.int_status;
self.int_status = 0;
},
_ => { println!("{}: reading from {:0x}", DEV_NAME, addr); data[0] = self.input; }, _ => { println!("{}: reading from {:0x}", DEV_NAME, addr); data[0] = self.input; },
} }
@ -154,6 +186,9 @@ impl Addressable for MC68681 {
REG_CTLR_WR => { REG_CTLR_WR => {
self.timer = (self.timer & 0xFF00) | (data[0] as u16); self.timer = (self.timer & 0xFF00) | (data[0] as u16);
}, },
REG_IMR_WR => {
self.int_mask = data[0];
},
REG_IVR_WR => { REG_IVR_WR => {
self.int_vector = data[0]; self.int_vector = data[0];
}, },

View File

@ -86,8 +86,19 @@ impl System {
Ok(()) Ok(())
} }
pub fn trigger_interrupt(&self, number: u8) { pub fn trigger_interrupt(&self, number: u8) -> Result<(), Error> {
// TODO how does this find the specific device it's connected to? // TODO how does this find the specific device it's connected to?
// TODO for the time being, this will find the first device to handle it or fail
for dev in &self.devices {
match dev {
Device::Interruptable(dev) => {
return dev.borrow_mut().handle_interrupt(&self, number);
},
_ => { },
}
}
return Err(Error::new(&format!("unhandled interrupt: {:x}", number)));
} }
pub fn exit_error(&mut self) { pub fn exit_error(&mut self) {