From 8bb43f61ee426d1aa4484d41fd2ca4ac7f21d6ba Mon Sep 17 00:00:00 2001 From: transistor Date: Fri, 8 Oct 2021 10:52:15 -0700 Subject: [PATCH] Fixed interrupts and added tx enable for OS buffered output --- binaries/kernel.bin | Bin 58320 -> 58036 bytes src/cpus/m68k/debugger.rs | 1 + src/cpus/m68k/execute.rs | 59 ++++++++---- src/cpus/m68k/state.rs | 35 +++++++- src/main.rs | 15 ++-- src/peripherals/ata.rs | 10 ++- src/peripherals/mc68681.rs | 178 ++++++++++++++++++++++++++++++------- src/system.rs | 9 +- todo.txt | 5 ++ 9 files changed, 251 insertions(+), 61 deletions(-) diff --git a/binaries/kernel.bin b/binaries/kernel.bin index fc35300e5c43d00ba5d2ca79176cb0478bf132fb..48554d4c0b88f4cb1a034f35a6ae8912d849c673 100755 GIT binary patch delta 9622 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 B{{jF2 delta 9898 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 { + self.debugger.use_tracing = false; self.debugger.use_debugger = false; return Ok(true); }, diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index b80a793..b5dd2f9 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -17,7 +17,7 @@ use super::decode::{ sign_extend_to_long }; -use super::state::{MC68010, Status, Flags}; +use super::state::{MC68010, Status, Flags, InterruptPriority}; impl Steppable for MC68010 { fn step(&mut self, system: &System) -> Result { @@ -31,8 +31,19 @@ impl Steppable for MC68010 { } impl Interruptable for MC68010 { - fn handle_interrupt(&mut self, _system: &System, number: u8) -> Result<(), Error> { - self.state.status = Status::PendingExecption(number); + fn interrupt_state_change(&mut self, system: &System, state: bool, priority: u8, number: u8) -> Result<(), Error> { + let ipl = if state { + InterruptPriority::from_u8(priority) + } else { + InterruptPriority::NoInterrupt + }; + + if ipl != self.state.pending_ipl { + self.state.pending_ipl = ipl; + if ipl != InterruptPriority::NoInterrupt { + self.state.ipl_ack_num = number; + } + } Ok(()) } } @@ -62,22 +73,40 @@ impl MC68010 { self.execute_current(system)?; self.timer.cycle.end(timer); - if (self.timer.cycle.events % 500) == 0 { - println!("{}", self.timer); - } + //if (self.timer.cycle.events % 500) == 0 { + // println!("{}", self.timer); + //} + + self.check_pending_interrupts(system)?; Ok(()) }, - Status::PendingExecption(num) => { - self.exception(system, num)?; - self.state.status = Status::Running; - 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; + + if self.state.pending_ipl != InterruptPriority::NoInterrupt { + let priority_mask = ((self.state.sr & 0x700) >> 8) as u8; + + if (pending_ipl >= priority_mask || pending_ipl == 7) && pending_ipl >= current_ipl { + self.state.current_ipl = self.state.pending_ipl; + self.exception(system, self.state.ipl_ack_num)?; + return Ok(()); + } + } + + if pending_ipl < current_ipl { + self.state.current_ipl = self.state.pending_ipl; + } + + Ok(()) + } + pub fn exception(&mut self, system: &System, number: u8) -> Result<(), Error> { - println!("raising exeception {:x}", number); + println!("raising exception {}", number); let offset = (number as u16) << 2; self.push_word(system, offset)?; self.push_long(system, self.state.pc)?; @@ -133,7 +162,7 @@ impl MC68010 { self.set_logic_flags(result, size); }, Instruction::ANDtoCCR(value) => { - self.state.sr = self.state.sr | value as u16; + self.state.sr = self.state.sr | (value as u16); }, Instruction::ANDtoSR(value) => { self.state.sr = self.state.sr | value; @@ -244,7 +273,7 @@ impl MC68010 { self.set_logic_flags(result, size); }, Instruction::EORtoCCR(value) => { - self.state.sr = self.state.sr ^ value as u16; + self.state.sr = self.state.sr ^ (value as u16); }, Instruction::EORtoSR(value) => { self.state.sr = self.state.sr ^ value; @@ -431,7 +460,7 @@ impl MC68010 { self.set_logic_flags(result, size); }, Instruction::ORtoCCR(value) => { - self.state.sr = self.state.sr | value as u16; + self.state.sr = self.state.sr | (value as u16); }, Instruction::ORtoSR(value) => { self.state.sr = self.state.sr | value; diff --git a/src/cpus/m68k/state.rs b/src/cpus/m68k/state.rs index 467b37b..36722c0 100644 --- a/src/cpus/m68k/state.rs +++ b/src/cpus/m68k/state.rs @@ -29,13 +29,43 @@ pub const ERR_ILLEGAL_INSTRUCTION: u32 = 4; pub enum Status { Init, Running, - PendingExecption(u8), Stopped, Halted, } +#[repr(u8)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum InterruptPriority { + NoInterrupt = 0, + Level1 = 1, + Level2 = 2, + Level3 = 3, + Level4 = 4, + Level5 = 5, + Level6 = 6, + Level7 = 7, +} + +impl InterruptPriority { + pub fn from_u8(priority: u8) -> InterruptPriority { + match priority { + 0 => InterruptPriority::NoInterrupt, + 1 => InterruptPriority::Level1, + 2 => InterruptPriority::Level2, + 3 => InterruptPriority::Level3, + 4 => InterruptPriority::Level4, + 5 => InterruptPriority::Level5, + 6 => InterruptPriority::Level6, + _ => InterruptPriority::Level7, + } + } +} + pub struct MC68010State { pub status: Status, + pub current_ipl: InterruptPriority, + pub pending_ipl: InterruptPriority, + pub ipl_ack_num: u8, pub pc: u32, pub sr: u16, @@ -51,6 +81,9 @@ impl MC68010State { pub fn new() -> MC68010State { MC68010State { status: Status::Init, + current_ipl: InterruptPriority::NoInterrupt, + pending_ipl: InterruptPriority::NoInterrupt, + ipl_ack_num: 0, pc: 0, sr: FLAGS_ON_RESET, diff --git a/src/main.rs b/src/main.rs index 37057e0..2c4c7fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,10 +38,9 @@ fn main() { let mut cpu = MC68010::new(); //cpu.enable_tracing(); - //cpu.add_breakpoint(0x0c94); - //cpu.add_breakpoint(0x103234); - //cpu.add_breakpoint(0x224); - //cpu.add_breakpoint(0x106ed2); + //cpu.add_breakpoint(0x10781a); + //cpu.add_breakpoint(0x10bc9c); + //cpu.add_breakpoint(0x106a94); system.add_interruptable_device(wrap_interruptable(cpu)).unwrap(); loop { @@ -56,13 +55,13 @@ fn main() { /* // TODO I need to add a way to decode and dump the assembly for a section of code, in debugger - cpu.state.pc = 0x00100000; - cpu.state.pc = 0x0010c270; + cpu.enable_tracing(); + cpu.state.pc = 0x0010781a; while cpu.is_running() { - match cpu.decode_next(&mut space) { + match cpu.decode_next(&system) { Ok(()) => { }, Err(err) => { - cpu.dump_state(&mut space); + cpu.dump_state(&system); panic!("{:?}", err); }, } diff --git a/src/peripherals/ata.rs b/src/peripherals/ata.rs index 3b63cc3..bd64eeb 100644 --- a/src/peripherals/ata.rs +++ b/src/peripherals/ata.rs @@ -74,13 +74,19 @@ impl Addressable for AtaDevice { let offset = ((self.selected_sector * ATA_SECTOR_SIZE) + (ATA_SECTOR_SIZE -1 - self.selected_count)) as usize; data[0] = self.contents[offset]; data[1] = self.contents[offset + 1]; -println!(">> {:x}{:x}", data[0], data[1]); + if self.selected_count == 0 { + self.selected_sector = 0; + self.selected_count = 0; + } }, ATA_REG_DATA_BYTE => { self.selected_count -= 1; let offset = ((self.selected_sector * ATA_SECTOR_SIZE) + (ATA_SECTOR_SIZE - 1 - self.selected_count)) as usize; data[0] = self.contents[offset]; -println!(">> {:x}", data[0]); + if self.selected_count == 0 { + self.selected_sector = 0; + self.selected_count = 0; + } }, ATA_REG_STATUS => { data[0] = ATA_ST_DATA_READY; diff --git a/src/peripherals/mc68681.rs b/src/peripherals/mc68681.rs index f984007..1faeae8 100644 --- a/src/peripherals/mc68681.rs +++ b/src/peripherals/mc68681.rs @@ -19,6 +19,14 @@ const REG_CSRA_WR: Address = 0x03; const REG_CRA_WR: Address = 0x05; const REG_TBA_WR: Address = 0x07; const REG_RBA_RD: Address = 0x07; + +const REG_MR1B_MR2B: Address = 0x700011; +const REG_SRB_RD: Address = 0x700013; +const REG_CSRB_WR: Address = 0x700013; +const REG_CRB_WR: Address = 0x700015; +const REG_TBB_WR: Address = 0x700017; +const REG_RBB_RD: Address = 0x700017; + const REG_ACR_WR: Address = 0x09; const REG_CTUR_WR: Address = 0x0D; @@ -63,26 +71,47 @@ const DEV_NAME: &'static str = "mc68681"; pub struct MC68681 { pub tty: Option, - pub status: u8, - pub input: u8, + pub acr: u8, + pub status_a: u8, + pub input_a: u8, + pub tx_a_enabled: bool, + pub rx_a_enabled: bool, + pub status_b: u8, + pub input_b: u8, + pub tx_b_enabled: bool, + pub rx_b_enabled: bool, pub int_mask: u8, pub int_status: u8, pub int_vector: u8, - pub int_edge_trigger: u8, - pub timer: u16, + pub is_interrupt: bool, + pub timer_preload: u16, + pub timer_count: u16, + pub is_timing: bool, } impl MC68681 { pub fn new() -> Self { MC68681 { tty: None, - status: 0x0C, - input: 0, + acr: 0, + + status_a: 0, + input_a: 0, + tx_a_enabled: false, + rx_a_enabled: false, + status_b: 0, + input_b: 0, + tx_b_enabled: false, + rx_b_enabled: false, + int_mask: 0, int_status: 0, int_vector: 0, - int_edge_trigger: 0, - timer: 0, + is_interrupt: false, + + timer_preload: 0, + timer_count: 0, + is_timing: true, } } @@ -107,14 +136,15 @@ impl MC68681 { } pub fn step_internal(&mut self, system: &System) -> Result<(), Error> { - if !self.rx_ready() && self.tty.is_some() { + if self.rx_a_enabled && !self.rx_ready() && self.tty.is_some() { let mut buf = [0; 1]; let tty = self.tty.as_mut().unwrap(); match tty.read(&mut buf) { Ok(count) => { println!("READ {:?}", count); - self.input = buf[0]; - self.status |= SR_RX_READY; + self.input_a = buf[0]; + self.status_a |= SR_RX_READY; + self.int_status |= ISR_CH_A_RX_READY_FULL; }, Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { }, Err(err) => { @@ -123,22 +153,39 @@ 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.is_timing { + self.timer_count = self.timer_count.wrapping_sub(1); + + if self.timer_count == 0 { + self.int_status |= ISR_TIMER_CHANGE; + if (self.acr & 0x40) == 0 { + self.is_timing = false; + } else { + self.timer_count = self.timer_preload; + } + } } - if (self.int_edge_trigger & self.int_mask) != 0 { - system.trigger_interrupt(self.int_vector)?; - self.int_edge_trigger = 0; - } + self.check_interrupt_state(system)?; Ok(()) } + fn check_interrupt_state(&mut self, system: &System) -> Result<(), Error> { + if !self.is_interrupt && (self.int_status & self.int_mask) != 0 { + self.is_interrupt = true; + system.change_interrupt_state(self.is_interrupt, 4, self.int_vector)?; + } + + if self.is_interrupt && (self.int_status & self.int_mask) == 0 { + self.is_interrupt = false; + system.change_interrupt_state(self.is_interrupt, 4, self.int_vector)?; + } + Ok(()) + } + pub fn rx_ready(&self) -> bool { - (self.status & SR_RX_READY) != 0 + (self.status_a & SR_RX_READY) != 0 } } @@ -150,41 +197,110 @@ impl Addressable for MC68681 { fn read(&mut self, addr: Address, count: usize) -> Result, Error> { let mut data = vec![0; count]; - // TODO this is temporary - //self.step(); + if addr != REG_SRA_RD && addr != REG_SRB_RD { + println!("{}: reading from {:0x}", DEV_NAME, addr); + } match addr { REG_SRA_RD => { - data[0] = self.status + data[0] = self.status_a }, REG_RBA_RD => { - data[0] = self.input; - self.status &= !SR_RX_READY; + data[0] = self.input_a; + self.status_a &= !SR_RX_READY; + self.int_status &= !ISR_CH_A_RX_READY_FULL; + }, + REG_SRB_RD => { + data[0] = self.status_b + }, + REG_RBB_RD => { + data[0] = self.input_b; + self.status_b &= !SR_RX_READY; + self.int_status &= !ISR_CH_B_RX_READY_FULL; }, REG_ISR_RD => { data[0] = self.int_status; - self.int_status = 0; }, - _ => { println!("{}: reading from {:0x}", DEV_NAME, addr); data[0] = self.input; }, + REG_START_RD => { + self.timer_count = self.timer_preload; + self.is_timing = true; + }, + REG_STOP_RD => { + self.int_status &= !ISR_TIMER_CHANGE; + if (self.acr & 0x40) == 0 { + // Counter Mode + self.is_timing = false; + self.timer_count = self.timer_preload; + } else { + // Timer Mode + // Do nothing except reset the ISR bit + } + }, + _ => { }, } Ok(data) } fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { + println!("{}: writing {:0x} to {:0x}", DEV_NAME, data[0], addr); match addr { //REG_MR1A_MR2A | REG_ACR_WR => { // // TODO config //}, + REG_ACR_WR => { + self.acr = data[0]; + } REG_TBA_WR => { - println!("{}: {}", DEV_NAME, data[0] as char); + println!("{}a: write {}", DEV_NAME, data[0] as char); self.tty.as_mut().map(|tty| tty.write_all(&[data[0]])); }, + REG_CRA_WR => { + let rx_cmd = (data[0] & 0x03); + if rx_cmd == 0b01 { + self.rx_a_enabled = true; + } else if rx_cmd == 0b10 { + self.rx_a_enabled = false; + } + + let tx_cmd = ((data[0] & 0x0C) >> 2); + if tx_cmd == 0b01 { + self.tx_a_enabled = true; + self.status_a |= SR_TX_READY | SR_TX_EMPTY; + self.int_status |= ISR_CH_A_TX_READY; + } else if tx_cmd == 0b10 { + self.tx_a_enabled = false; + self.status_a &= !(SR_TX_READY | SR_TX_EMPTY); + self.int_status &= !ISR_CH_A_TX_READY; + } + }, + REG_TBB_WR => { + println!("{}b: write {:x}", DEV_NAME, data[0]); + }, + REG_CRB_WR => { + let rx_cmd = (data[0] & 0x03); + if rx_cmd == 0b01 { + self.rx_b_enabled = true; + } else if rx_cmd == 0b10 { + self.rx_b_enabled = false; + } + + let tx_cmd = ((data[0] & 0x0C) >> 2); + if tx_cmd == 0b01 { + self.tx_b_enabled = true; + self.status_b |= SR_TX_READY | SR_TX_EMPTY; + self.int_status |= ISR_CH_B_TX_READY; + } else if tx_cmd == 0b10 { + self.tx_b_enabled = false; + self.status_b &= !(SR_TX_READY | SR_TX_EMPTY); + self.int_status &= !ISR_CH_B_TX_READY; + } + }, REG_CTUR_WR => { - self.timer = (self.timer & 0x00FF) | ((data[0] as u16) << 8); + self.timer_preload = (self.timer_preload & 0x00FF) | ((data[0] as u16) << 8); }, REG_CTLR_WR => { - self.timer = (self.timer & 0xFF00) | (data[0] as u16); + self.timer_preload = (self.timer_preload & 0xFF00) | (data[0] as u16); }, REG_IMR_WR => { self.int_mask = data[0]; @@ -192,7 +308,7 @@ impl Addressable for MC68681 { REG_IVR_WR => { self.int_vector = data[0]; }, - _ => { println!("{}: writing {:0x} to {:0x}", DEV_NAME, data[0], addr); }, + _ => { }, } Ok(()) } diff --git a/src/system.rs b/src/system.rs index 88cb649..fff4824 100644 --- a/src/system.rs +++ b/src/system.rs @@ -15,7 +15,7 @@ pub trait Steppable { } pub trait Interruptable { - fn handle_interrupt(&mut self, system: &System, number: u8) -> Result<(), Error>; + fn interrupt_state_change(&mut self, system: &System, state: bool, priority: u8, number: u8) -> Result<(), Error>; } pub trait AddressableDevice: Addressable + Steppable { } @@ -86,14 +86,15 @@ impl System { Ok(()) } - pub fn trigger_interrupt(&self, number: u8) -> Result<(), Error> { + pub fn change_interrupt_state(&self, state: bool, priority: u8, 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 + println!("system: interrupt state changed to {} ({})", state, priority); for dev in &self.devices { match dev { Device::Interruptable(dev) => { - return dev.borrow_mut().handle_interrupt(&self, number); + return dev.borrow_mut().interrupt_state_change(&self, state, priority, number); }, _ => { }, } @@ -112,7 +113,7 @@ impl System { } pub struct InterruptController { - + } diff --git a/todo.txt b/todo.txt index 05f06f6..9851445 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,9 @@ +* add a Signal struct which records its val and prev val, and can be used for state change things like interrupts + the int controller coild have multiple for different prioritis, and could maybe be activated by multiple sources +* the remaining issue with the shell is that putchar_buffered requires the TX interrupt and TX enable/disable commands to work in order to trigger a write + + * how will you add the cpu, which is not addressable, but is steppable, and also interruptable... what else? * should you simulate bus arbitration? * if the bus had an Rc>>, then it could be like AddressSpace used to be, with it's own Addressable, and then you could