diff --git a/src/libvm/src/interrupt.rs b/src/libvm/src/interrupt.rs index 80fb5a6..0f6f004 100644 --- a/src/libvm/src/interrupt.rs +++ b/src/libvm/src/interrupt.rs @@ -26,7 +26,7 @@ pub const IVT_LENGTH: usize = 512; pub struct Interrupt(u64); const ENABLED_MASK: u64 = 0x8000_0000_0000_0000; -const ADDR_MASK: u64 = 0x07ff_ffff_ffff_ffff; +const ADDR_MASK: u64 = 0x1fff_ffff_ffff_ffff; impl Interrupt { pub fn enabled(&self) -> bool { @@ -39,11 +39,11 @@ impl Interrupt { } pub fn addr(&self) -> Addr { - Addr((self.0 & ADDR_MASK) << 5) + Addr((self.0 & ADDR_MASK) << 3) } pub fn set_addr(&mut self, addr: Addr) { - let addr = (addr.0 >> 5) & ADDR_MASK; + let addr = (addr.0 >> 3) & ADDR_MASK; self.0 &= !ADDR_MASK; self.0 |= addr; } diff --git a/src/libvm/src/state.rs b/src/libvm/src/state.rs index f2cfb6c..8f11818 100644 --- a/src/libvm/src/state.rs +++ b/src/libvm/src/state.rs @@ -181,23 +181,23 @@ impl State { let ip = return_ip; let flags = self.get_reg_unchecked(FLAGS); let status = self.status(); - let r0 = self.get_reg_unchecked(R00); - let r1 = self.get_reg_unchecked(R01); self.push(Source::Imm(fp))?; self.push(Source::Imm(ip))?; self.push(Source::Imm(flags))?; self.push(Source::Imm(status))?; - self.push(Source::Imm(r0))?; - self.push(Source::Imm(r1))?; + + // push R0 .. R31 + for reg in R00 ..= R31 { + self.push(Source::Reg(reg))?; + } let sp = self.sp(); self.set_reg_unchecked(FP, sp - 48); - self.set_reg_unchecked(IP, interrupt.addr().0); self.set_reg_unchecked(R00, index as u64); self.set_reg_unchecked(R01, aux); - Ok(self.ip()) + Ok(interrupt.addr().0) } /// Exit/return from the current interrupt. @@ -207,8 +207,10 @@ impl State { self.set_reg_unchecked(SP, sp); - self.pop(Dest::Reg(R01))?; - self.pop(Dest::Reg(R00))?; + // pop R31 .. R0 + for reg in R31 ..= R00 { + self.pop(Dest::Reg(reg))?; + } self.pop(Dest::Reg(STATUS))?; self.pop(Dest::Reg(FLAGS))?; self.pop(Dest::Reg(IP))?; @@ -258,11 +260,14 @@ impl State { } } Inst::IDiv(d, s) => { - // TODO : catch divide by zero let dest = self.load_dest(d)? as i64; let source = self.load_source(s)? as i64; - let value = dest.wrapping_div(source); - self.store_dest(d, value as u64)?; + if source == 0 { + next_ip = self.interrupt(next_ip, DIVIDE_BY_ZERO, 0)?; + } else { + let value = dest.wrapping_div(source); + self.store_dest(d, value as u64)?; + } } Inst::Mod(d, s) => { let value = self.load_dest(d)? % self.load_source(s)?;