finished initial interrupts implementation

This commit is contained in:
2025-06-25 00:13:55 +01:00
parent 92c4660a4d
commit 82b99c127c
5 changed files with 54 additions and 18 deletions
+1 -4
View File
@@ -11,10 +11,7 @@ pub fn codegen(nodes: Vec<Node>) -> Result<Vec<Instruction>, AssembleError> {
let mut instructions = vec![]; let mut instructions = vec![];
for node in nodes { for node in nodes {
instructions.push( instructions.push(build_instruction(&node)?);
build_instruction(&node)
.unwrap_or_else(|_| panic!("Failed to build instruction: {node:?}")),
);
} }
println!("------------------------"); println!("------------------------");
+3 -1
View File
@@ -10,7 +10,9 @@ pub enum Interrupt {
pub type Address = u32; pub type Address = u32;
impl Interrupt { impl Interrupt {
const fn as_u8(self) -> u8 { // someone tell clippy to stfu.
#[allow(clippy::must_use_candidate)]
pub const fn as_u8(self) -> u8 {
match self { match self {
Self::Breakpoint => 0, Self::Breakpoint => 0,
Self::HardFault => 1, Self::HardFault => 1,
+5 -3
View File
@@ -54,12 +54,14 @@ impl Encode for Instruction {
], ],
no_args: [Nop, IntReturn, Halt], no_args: [Nop, IntReturn, Halt],
special: [ special: [
Self::Interrupt(_) => todo!(),
Self::Data(data) => data, Self::Data(data) => data,
Self::Interrupt(interrupt) => {
let opcode = u32::from(self.opcode());
(opcode << 26) | u32::from(interrupt.as_u8())
},
Self::Segment(segment) => { Self::Segment(segment) => {
let opcode = u32::from(self.opcode()); let opcode = u32::from(self.opcode());
let segment = segment as u8; (opcode << 26) | u32::from(segment as u8)
(opcode << 26) | u32::from(segment)
} }
] ]
) )
+11 -3
View File
@@ -212,8 +212,14 @@ pub fn run_emulator(
Ok(instruction) => instruction, Ok(instruction) => instruction,
Err(why) => { Err(why) => {
let pcx = processor.get(Register::Pcx); let pcx = processor.get(Register::Pcx);
eprintln!("Could not decode instruction at {pcx:x}. Reason: {why}"); report_err(
continue; 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) { 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())); let _ = state_tx.send(StateUpdate::Error(why.to_string()));
} }
+34 -7
View File
@@ -116,15 +116,42 @@ impl Processor {
*self.reg(Register::Pcx) = self.get(reg) + u32::from(offset); *self.reg(Register::Pcx) = self.get(reg) + u32::from(offset);
} }
pub fn begin_interrupt(&mut self, _int: Interrupt) { pub fn begin_interrupt(
// first we get the address of the interrupt descriptor table. &mut self,
todo!(); 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 // TODO: remove this once implemented
#[allow(clippy::needless_pass_by_ref_mut)] #[allow(clippy::needless_pass_by_ref_mut)]
fn end_interrupt(&mut self) { fn end_interrupt(&mut self) -> Result<(), ProcessorError> {
todo!(); 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> { 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 return address is saved to the RET register.
// - The stack base ptr is set to the kernel stack. // - The stack base ptr is set to the kernel stack.
Self::Interrupt(interrupt_code) => { Self::Interrupt(interrupt_code) => {
cpu.begin_interrupt(interrupt_code); cpu.begin_interrupt(interrupt_code)?;
} }
// Returns from an interrupt, // Returns from an interrupt,
Self::IntReturn => { Self::IntReturn => {
cpu.end_interrupt(); cpu.end_interrupt()?;
} }
// Halts the processor. // Halts the processor.