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:
@@ -26,7 +26,7 @@ pub const IVT_LENGTH: usize = 512;
|
|||||||
pub struct Interrupt(u64);
|
pub struct Interrupt(u64);
|
||||||
|
|
||||||
const ENABLED_MASK: u64 = 0x8000_0000_0000_0000;
|
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 {
|
impl Interrupt {
|
||||||
pub fn enabled(&self) -> bool {
|
pub fn enabled(&self) -> bool {
|
||||||
@@ -39,11 +39,11 @@ impl Interrupt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn addr(&self) -> Addr {
|
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) {
|
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_MASK;
|
||||||
self.0 |= addr;
|
self.0 |= addr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,23 +181,23 @@ impl State {
|
|||||||
let ip = return_ip;
|
let ip = return_ip;
|
||||||
let flags = self.get_reg_unchecked(FLAGS);
|
let flags = self.get_reg_unchecked(FLAGS);
|
||||||
let status = self.status();
|
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(fp))?;
|
||||||
self.push(Source::Imm(ip))?;
|
self.push(Source::Imm(ip))?;
|
||||||
self.push(Source::Imm(flags))?;
|
self.push(Source::Imm(flags))?;
|
||||||
self.push(Source::Imm(status))?;
|
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();
|
let sp = self.sp();
|
||||||
self.set_reg_unchecked(FP, sp - 48);
|
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(R00, index as u64);
|
||||||
self.set_reg_unchecked(R01, aux);
|
self.set_reg_unchecked(R01, aux);
|
||||||
|
|
||||||
Ok(self.ip())
|
Ok(interrupt.addr().0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exit/return from the current interrupt.
|
/// Exit/return from the current interrupt.
|
||||||
@@ -207,8 +207,10 @@ impl State {
|
|||||||
|
|
||||||
self.set_reg_unchecked(SP, sp);
|
self.set_reg_unchecked(SP, sp);
|
||||||
|
|
||||||
self.pop(Dest::Reg(R01))?;
|
// pop R31 .. R0
|
||||||
self.pop(Dest::Reg(R00))?;
|
for reg in R31 ..= R00 {
|
||||||
|
self.pop(Dest::Reg(reg))?;
|
||||||
|
}
|
||||||
self.pop(Dest::Reg(STATUS))?;
|
self.pop(Dest::Reg(STATUS))?;
|
||||||
self.pop(Dest::Reg(FLAGS))?;
|
self.pop(Dest::Reg(FLAGS))?;
|
||||||
self.pop(Dest::Reg(IP))?;
|
self.pop(Dest::Reg(IP))?;
|
||||||
@@ -258,12 +260,15 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Inst::IDiv(d, s) => {
|
Inst::IDiv(d, s) => {
|
||||||
// TODO : catch divide by zero
|
|
||||||
let dest = self.load_dest(d)? as i64;
|
let dest = self.load_dest(d)? as i64;
|
||||||
let source = self.load_source(s)? 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);
|
let value = dest.wrapping_div(source);
|
||||||
self.store_dest(d, value as u64)?;
|
self.store_dest(d, value as u64)?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Inst::Mod(d, s) => {
|
Inst::Mod(d, s) => {
|
||||||
let value = self.load_dest(d)? % self.load_source(s)?;
|
let value = self.load_dest(d)? % self.load_source(s)?;
|
||||||
self.store_dest(d, value)?;
|
self.store_dest(d, value)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user