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 {
fn handle_interrupt(&mut self, system: &System, number: u8) -> Result<(), Error> {
self.exception(system, number)
fn handle_interrupt(&mut self, _system: &System, number: u8) -> Result<(), Error> {
self.state.status = Status::PendingExecption(number);
Ok(())
}
}
@ -67,10 +68,16 @@ impl MC68010 {
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> {
println!("raising exeception {:x}", number);
let offset = (number as u16) << 2;
self.push_word(system, offset)?;
self.push_long(system, self.state.pc)?;

View File

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

View File

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

View File

@ -48,13 +48,27 @@ const SR_RX_FULL: u8 = 0x02;
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";
pub struct MC68681 {
pub tty: Option<PtyMaster>,
pub status: u8,
pub input: u8,
pub int_mask: u8,
pub int_status: u8,
pub int_vector: u8,
pub int_edge_trigger: u8,
pub timer: u16,
}
@ -64,7 +78,10 @@ impl MC68681 {
tty: None,
status: 0x0C,
input: 0,
int_mask: 0,
int_status: 0,
int_vector: 0,
int_edge_trigger: 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() {
let mut buf = [0; 1];
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(())
}
@ -133,6 +161,10 @@ impl Addressable for MC68681 {
data[0] = self.input;
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; },
}
@ -154,6 +186,9 @@ impl Addressable for MC68681 {
REG_CTLR_WR => {
self.timer = (self.timer & 0xFF00) | (data[0] as u16);
},
REG_IMR_WR => {
self.int_mask = data[0];
},
REG_IVR_WR => {
self.int_vector = data[0];
},

View File

@ -86,8 +86,19 @@ impl System {
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 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) {