Fix dumb mistake in address calculation for interrupts, add more registers to interrupt call stack

Interrupts need to be on 8-byte (or 64-bit) bounds. I had mistakenly
decided to shift right by 5 (which isn't even dividing by 64, it's 32)
-but since this an address pointing at byte ranges, that should be
divided by 8, or >> 3.

Additionally, interrupts add all 32 general purpose registers to the
stack because otherwise they become useless.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-03-09 18:24:54 -04:00
parent 9e82663b2a
commit 8c4a9991fd
2 changed files with 19 additions and 14 deletions

View File

@@ -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;
}

View File

@@ -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,12 +260,15 @@ 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;
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)?;
self.store_dest(d, value)?;