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 {
|
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)?;
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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];
|
||||||
},
|
},
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user