fox32+fox32core: Rework the interrupt system a little bit
This commit is contained in:
parent
81ccead64c
commit
a8d92c69b2
34
src/cpu.rs
34
src/cpu.rs
|
@ -9,22 +9,25 @@ const DEBUG: bool = false;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Flag {
|
pub struct Flag {
|
||||||
|
pub interrupt: bool,
|
||||||
pub carry: bool,
|
pub carry: bool,
|
||||||
pub zero: bool,
|
pub zero: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::From<Flag> for u8 {
|
impl std::convert::From<Flag> for u8 {
|
||||||
fn from(flag: Flag) -> u8 {
|
fn from(flag: Flag) -> u8 {
|
||||||
(if flag.carry { 1 } else { 0 }) << 1 |
|
(if flag.interrupt { 1 } else { 0 }) << 2 |
|
||||||
(if flag.zero { 1 } else { 0 }) << 0
|
(if flag.carry { 1 } else { 0 }) << 1 |
|
||||||
|
(if flag.zero { 1 } else { 0 }) << 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::From<u8> for Flag {
|
impl std::convert::From<u8> for Flag {
|
||||||
fn from(byte: u8) -> Self {
|
fn from(byte: u8) -> Self {
|
||||||
let carry = ((byte >> 1) & 1) != 0;
|
let interrupt = ((byte >> 2) & 1) != 0;
|
||||||
let zero = ((byte >> 0) & 1) != 0;
|
let carry = ((byte >> 1) & 1) != 0;
|
||||||
Flag { carry, zero }
|
let zero = ((byte >> 0) & 1) != 0;
|
||||||
|
Flag { interrupt, carry, zero }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +50,6 @@ pub struct Cpu {
|
||||||
pub register: [u32; 32],
|
pub register: [u32; 32],
|
||||||
pub flag: Flag,
|
pub flag: Flag,
|
||||||
pub halted: bool,
|
pub halted: bool,
|
||||||
pub interrupts_enabled: bool,
|
|
||||||
pub interrupts_paused: bool, // stores the previous state of interrupts_enabled while servicing an interrupt
|
|
||||||
|
|
||||||
pub bus: Bus,
|
pub bus: Bus,
|
||||||
}
|
}
|
||||||
|
@ -59,10 +60,8 @@ impl Cpu {
|
||||||
instruction_pointer: 0xF0000000,
|
instruction_pointer: 0xF0000000,
|
||||||
stack_pointer: 0x00000000,
|
stack_pointer: 0x00000000,
|
||||||
register: [0; 32],
|
register: [0; 32],
|
||||||
flag: Flag { zero: false, carry: false },
|
flag: Flag { interrupt: false, carry: false, zero: false },
|
||||||
halted: false,
|
halted: false,
|
||||||
interrupts_enabled: false,
|
|
||||||
interrupts_paused: false,
|
|
||||||
bus,
|
bus,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,9 +208,8 @@ impl Cpu {
|
||||||
word
|
word
|
||||||
}
|
}
|
||||||
pub fn interrupt(&mut self, interrupt: Interrupt) {
|
pub fn interrupt(&mut self, interrupt: Interrupt) {
|
||||||
if DEBUG { println!("interrupt(): enabled: {}, paused: {}", self.interrupts_enabled, self.interrupts_paused); }
|
if DEBUG { println!("interrupt(): enabled: {}", self.flag.interrupt); }
|
||||||
if self.interrupts_enabled && !self.interrupts_paused {
|
if self.flag.interrupt {
|
||||||
self.interrupts_paused = true; // prevent interrupts while already servicing an interrupt
|
|
||||||
match interrupt {
|
match interrupt {
|
||||||
Interrupt::Request(vector) => {
|
Interrupt::Request(vector) => {
|
||||||
self.handle_interrupt(vector as u16);
|
self.handle_interrupt(vector as u16);
|
||||||
|
@ -237,6 +235,7 @@ impl Cpu {
|
||||||
let address = self.bus.memory.read_32(address_of_pointer);
|
let address = self.bus.memory.read_32(address_of_pointer);
|
||||||
self.push_stack_32(self.instruction_pointer);
|
self.push_stack_32(self.instruction_pointer);
|
||||||
self.push_stack_8(u8::from(self.flag));
|
self.push_stack_8(u8::from(self.flag));
|
||||||
|
self.flag.interrupt = false; // prevent interrupts while already servicing an interrupt
|
||||||
self.instruction_pointer = address;
|
self.instruction_pointer = address;
|
||||||
}
|
}
|
||||||
fn handle_exception(&mut self, vector: u16, operand: Option<u32>) {
|
fn handle_exception(&mut self, vector: u16, operand: Option<u32>) {
|
||||||
|
@ -248,6 +247,7 @@ impl Cpu {
|
||||||
if let Some(operand) = operand {
|
if let Some(operand) = operand {
|
||||||
self.push_stack_32(operand);
|
self.push_stack_32(operand);
|
||||||
}
|
}
|
||||||
|
self.flag.interrupt = false; // prevent interrupts while already servicing an interrupt
|
||||||
self.instruction_pointer = address;
|
self.instruction_pointer = address;
|
||||||
}
|
}
|
||||||
// execute instruction from memory at the current instruction pointer
|
// execute instruction from memory at the current instruction pointer
|
||||||
|
@ -2574,8 +2574,6 @@ impl Cpu {
|
||||||
let instruction_pointer_offset = 2; // increment past opcode half
|
let instruction_pointer_offset = 2; // increment past opcode half
|
||||||
let should_run = self.check_condition(condition);
|
let should_run = self.check_condition(condition);
|
||||||
if should_run {
|
if should_run {
|
||||||
self.interrupts_enabled = self.interrupts_paused;
|
|
||||||
self.interrupts_paused = false;
|
|
||||||
self.flag = Flag::from(self.pop_stack_8());
|
self.flag = Flag::from(self.pop_stack_8());
|
||||||
self.pop_stack_32()
|
self.pop_stack_32()
|
||||||
} else {
|
} else {
|
||||||
|
@ -2651,8 +2649,7 @@ impl Cpu {
|
||||||
let instruction_pointer_offset = 2; // increment past opcode half
|
let instruction_pointer_offset = 2; // increment past opcode half
|
||||||
let should_run = self.check_condition(condition);
|
let should_run = self.check_condition(condition);
|
||||||
if should_run {
|
if should_run {
|
||||||
self.interrupts_enabled = true;
|
self.flag.interrupt = true;
|
||||||
self.interrupts_paused = false;
|
|
||||||
}
|
}
|
||||||
self.instruction_pointer + instruction_pointer_offset
|
self.instruction_pointer + instruction_pointer_offset
|
||||||
}
|
}
|
||||||
|
@ -2660,8 +2657,7 @@ impl Cpu {
|
||||||
let instruction_pointer_offset = 2; // increment past opcode half
|
let instruction_pointer_offset = 2; // increment past opcode half
|
||||||
let should_run = self.check_condition(condition);
|
let should_run = self.check_condition(condition);
|
||||||
if should_run {
|
if should_run {
|
||||||
self.interrupts_enabled = false;
|
self.flag.interrupt = false;
|
||||||
self.interrupts_paused = false;
|
|
||||||
}
|
}
|
||||||
self.instruction_pointer + instruction_pointer_offset
|
self.instruction_pointer + instruction_pointer_offset
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
runtime.step();
|
runtime.step();
|
||||||
}
|
}
|
||||||
if !runtime.interrupts_enabled_get() {
|
if !runtime.flag_interrupt_get() {
|
||||||
// the cpu was halted and interrupts are disabled
|
// the cpu was halted and interrupts are disabled
|
||||||
// at this point, the cpu is dead and cannot resume, break out of the loop
|
// at this point, the cpu is dead and cannot resume, break out of the loop
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,8 +4,8 @@ pub trait Runtime: Send {
|
||||||
fn halted_get(&mut self) -> bool;
|
fn halted_get(&mut self) -> bool;
|
||||||
fn halted_set(&mut self, halted: bool);
|
fn halted_set(&mut self, halted: bool);
|
||||||
|
|
||||||
fn interrupts_enabled_get(&mut self) -> bool;
|
fn flag_interrupt_get(&mut self) -> bool;
|
||||||
fn interrupts_enabled_set(&mut self, interrupts_enabled: bool);
|
fn flag_interrupt_set(&mut self, flag_interrupt: bool);
|
||||||
|
|
||||||
fn raise(&mut self, vector: u16);
|
fn raise(&mut self, vector: u16);
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ impl Runtime for crate::Cpu {
|
||||||
self.halted = halted
|
self.halted = halted
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interrupts_enabled_get(&mut self) -> bool {
|
fn flag_interrupt_get(&mut self) -> bool {
|
||||||
self.interrupts_enabled
|
self.flag.interrupt
|
||||||
}
|
}
|
||||||
fn interrupts_enabled_set(&mut self, interrupts_enabled: bool) {
|
fn flag_interrupt_set(&mut self, flag_interrupt: bool) {
|
||||||
self.interrupts_enabled = interrupts_enabled
|
self.flag.interrupt = flag_interrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raise(&mut self, vector: u16) {
|
fn raise(&mut self, vector: u16) {
|
||||||
|
@ -44,11 +44,11 @@ impl Runtime for fox32core::State {
|
||||||
*self.halted() = halted;
|
*self.halted() = halted;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interrupts_enabled_get(&mut self) -> bool {
|
fn flag_interrupt_get(&mut self) -> bool {
|
||||||
*self.interrupts_enabled()
|
*self.flag_interrupt()
|
||||||
}
|
}
|
||||||
fn interrupts_enabled_set(&mut self, interrupts_enabled: bool) {
|
fn flag_interrupt_set(&mut self, flag_interrupt: bool) {
|
||||||
*self.interrupts_enabled() = interrupts_enabled;
|
*self.flag_interrupt() = flag_interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raise(&mut self, vector: u16) {
|
fn raise(&mut self, vector: u16) {
|
||||||
|
|
|
@ -82,11 +82,11 @@ impl Runtime for CoreWrapped {
|
||||||
unsafe { (*self.inner()).halted_set(halted) }
|
unsafe { (*self.inner()).halted_set(halted) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interrupts_enabled_get(&mut self) -> bool {
|
fn flag_interrupt_get(&mut self) -> bool {
|
||||||
unsafe { (*self.inner()).interrupts_enabled_get() }
|
unsafe { (*self.inner()).flag_interrupt_get() }
|
||||||
}
|
}
|
||||||
fn interrupts_enabled_set(&mut self, interrupts_enabled: bool) {
|
fn flag_interrupt_set(&mut self, flag_interrupt: bool) {
|
||||||
unsafe { (*self.inner()).interrupts_enabled_set(interrupts_enabled) }
|
unsafe { (*self.inner()).flag_interrupt_set(flag_interrupt) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raise(&mut self, vector: u16) {
|
fn raise(&mut self, vector: u16) {
|
||||||
|
@ -114,4 +114,3 @@ impl Memory for CoreMemoryWrapped {
|
||||||
fn ram(&self) -> &mut MemoryRam { self.0.ram() }
|
fn ram(&self) -> &mut MemoryRam { self.0.ram() }
|
||||||
fn rom(&self) -> &mut MemoryRom { self.0.rom() }
|
fn rom(&self) -> &mut MemoryRom { self.0.rom() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user