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![];
for node in nodes {
instructions.push(
build_instruction(&node)
.unwrap_or_else(|_| panic!("Failed to build instruction: {node:?}")),
);
instructions.push(build_instruction(&node)?);
}
println!("------------------------");
+3 -1
View File
@@ -10,7 +10,9 @@ pub enum Interrupt {
pub type Address = u32;
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 {
Self::Breakpoint => 0,
Self::HardFault => 1,
+5 -3
View File
@@ -54,12 +54,14 @@ impl Encode for Instruction {
],
no_args: [Nop, IntReturn, Halt],
special: [
Self::Interrupt(_) => todo!(),
Self::Data(data) => data,
Self::Interrupt(interrupt) => {
let opcode = u32::from(self.opcode());
(opcode << 26) | u32::from(interrupt.as_u8())
},
Self::Segment(segment) => {
let opcode = u32::from(self.opcode());
let segment = segment as u8;
(opcode << 26) | u32::from(segment)
(opcode << 26) | u32::from(segment as u8)
}
]
)
+11 -3
View File
@@ -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()));
}
+34 -7
View File
@@ -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.