finished initial interrupts implementation
This commit is contained in:
@@ -212,8 +212,14 @@ pub fn run_emulator(
|
||||
Ok(instruction) => instruction,
|
||||
Err(why) => {
|
||||
let pcx = processor.get(Register::Pcx);
|
||||
eprintln!("Could not decode instruction at {pcx:x}. Reason: {why}");
|
||||
continue;
|
||||
report_err(
|
||||
state_tx,
|
||||
&format!(
|
||||
"Could not decode instruction at {pcx:x}. Reason: {why}"
|
||||
),
|
||||
&mut processor,
|
||||
);
|
||||
(pcx, Instruction::Nop)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -228,6 +234,8 @@ pub fn run_emulator(
|
||||
}
|
||||
|
||||
fn report_err(state_tx: &Sender<StateUpdate>, why: &str, processor: &mut Processor) {
|
||||
processor.begin_interrupt(Interrupt::HardFault);
|
||||
processor
|
||||
.begin_interrupt(Interrupt::HardFault)
|
||||
.expect("What kind of goofy ahh shenanigans did you do with your fault handler? At this point, the emulator can just crash. this is on you.");
|
||||
let _ = state_tx.send(StateUpdate::Error(why.to_string()));
|
||||
}
|
||||
|
||||
@@ -116,15 +116,42 @@ impl Processor {
|
||||
*self.reg(Register::Pcx) = self.get(reg) + u32::from(offset);
|
||||
}
|
||||
|
||||
pub fn begin_interrupt(&mut self, _int: Interrupt) {
|
||||
// first we get the address of the interrupt descriptor table.
|
||||
todo!();
|
||||
pub fn begin_interrupt(
|
||||
&mut self,
|
||||
interrupt: Interrupt,
|
||||
) -> Result<(), ProcessorError> {
|
||||
let idt = self.get(Register::Idr);
|
||||
|
||||
let addr = self
|
||||
.memory
|
||||
.read_word(idt + u32::from(interrupt.as_u8()) * 4)?;
|
||||
println!("INFO: Interrupt {interrupt:?} addr: {addr}");
|
||||
|
||||
self.push(self.get(Register::Pcx))?;
|
||||
*self.reg(Register::Pcx) = addr;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn push(&mut self, val: u32) -> Result<(), ProcessorError> {
|
||||
*self.reg(Register::Spr) -= 4;
|
||||
let reg = *self.reg(Register::Spr);
|
||||
self.memory.write_word(reg, val)
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Result<u32, ProcessorError> {
|
||||
let reg = *self.reg(Register::Spr);
|
||||
let val = self.memory.read_word(reg)?;
|
||||
*self.reg(Register::Spr) += 4;
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
// TODO: remove this once implemented
|
||||
#[allow(clippy::needless_pass_by_ref_mut)]
|
||||
fn end_interrupt(&mut self) {
|
||||
todo!();
|
||||
fn end_interrupt(&mut self) -> Result<(), ProcessorError> {
|
||||
let ret = self.pop()?;
|
||||
*self.reg(Register::Ret) = ret;
|
||||
*self.reg(Register::Pcx) = ret;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_stack(&mut self, n: u32) -> Result<Vec<u8>, ProcessorError> {
|
||||
@@ -382,12 +409,12 @@ impl Executable for Instruction {
|
||||
// - The return address is saved to the RET register.
|
||||
// - The stack base ptr is set to the kernel stack.
|
||||
Self::Interrupt(interrupt_code) => {
|
||||
cpu.begin_interrupt(interrupt_code);
|
||||
cpu.begin_interrupt(interrupt_code)?;
|
||||
}
|
||||
|
||||
// Returns from an interrupt,
|
||||
Self::IntReturn => {
|
||||
cpu.end_interrupt();
|
||||
cpu.end_interrupt()?;
|
||||
}
|
||||
|
||||
// Halts the processor.
|
||||
|
||||
Reference in New Issue
Block a user