mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-17 07:08:41 +00:00
Added interrupt triggering from mc68681
This commit is contained in:
parent
7bd7f3e64f
commit
ecbaf6a68b
@ -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)?;
|
||||
|
@ -29,6 +29,7 @@ pub const ERR_ILLEGAL_INSTRUCTION: u32 = 4;
|
||||
pub enum Status {
|
||||
Init,
|
||||
Running,
|
||||
PendingExecption(u8),
|
||||
Stopped,
|
||||
Halted,
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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];
|
||||
},
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user