Add interrupt struct and IVT reader
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::addr::Addr;
|
||||||
|
|
||||||
macro_rules! interrupts {
|
macro_rules! interrupts {
|
||||||
{
|
{
|
||||||
$($variant:ident = $value:expr),* $(,)?
|
$($variant:ident = $value:expr),* $(,)?
|
||||||
@@ -17,3 +19,32 @@ interrupts! {
|
|||||||
ILLEGAL_MEMORY_ADDRESS = 2,
|
ILLEGAL_MEMORY_ADDRESS = 2,
|
||||||
HARDWARE_EVENT = 3,
|
HARDWARE_EVENT = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const IVT_LENGTH: usize = 512;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct Interrupt(u64);
|
||||||
|
|
||||||
|
const ENABLED_MASK: u64 = 0x8000_0000_0000_0000;
|
||||||
|
const ADDR_MASK: u64 = 0x07ff_ffff_ffff_ffff;
|
||||||
|
|
||||||
|
impl Interrupt {
|
||||||
|
pub fn enabled(&self) -> bool {
|
||||||
|
(self.0 & ENABLED_MASK) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_enabled(&mut self, enabled: bool) {
|
||||||
|
let enabled = (enabled as u64) << 63;
|
||||||
|
self.0 |= enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addr(&self) -> Addr {
|
||||||
|
Addr((self.0 & ADDR_MASK) << 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_addr(&mut self, addr: Addr) {
|
||||||
|
let addr = (addr.0 >> 5) & ADDR_MASK;
|
||||||
|
self.0 &= !ADDR_MASK;
|
||||||
|
self.0 |= addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -58,31 +58,32 @@ impl Asm for DataSection {
|
|||||||
fn assemble(&self, session: &mut AsmSession) -> Result<Self::Out> {
|
fn assemble(&self, session: &mut AsmSession) -> Result<Self::Out> {
|
||||||
let names = names::get_section_names(self)?;
|
let names = names::get_section_names(self)?;
|
||||||
session.name_stack.push(names);
|
session.name_stack.push(names);
|
||||||
let section_len = self.len() as u64;
|
let content_len = self.len() as u64;
|
||||||
let (start, end) = match self.org {
|
let (start, end) = match self.org {
|
||||||
SectionOrg::Start(start) => (start, start + (section_len as u64)),
|
SectionOrg::Start(start) => (start, start + (content_len as u64)),
|
||||||
SectionOrg::StartEnd(start, end) => (start, end),
|
SectionOrg::StartEnd(start, end) => (start, end),
|
||||||
};
|
};
|
||||||
session.pos = Addr(start);
|
session.pos = Addr(start);
|
||||||
if start > end {
|
if start > end {
|
||||||
return Err(AsmError::StartGreaterThanEnd { start, end });
|
return Err(AsmError::StartGreaterThanEnd { start, end });
|
||||||
}
|
}
|
||||||
let len = end - start - 1;
|
let len = end - start;
|
||||||
if len > section_len {
|
if content_len > len {
|
||||||
return Err(AsmError::SectionTooShort {
|
return Err(AsmError::SectionTooShort {
|
||||||
|
name: self.name.clone(),
|
||||||
section_end: end,
|
section_end: end,
|
||||||
section_size: start + section_len,
|
section_size: start + content_len,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut contents = Vec::with_capacity(section_len as usize);
|
let mut contents = Vec::with_capacity(content_len as usize);
|
||||||
for line in self.lines.iter() {
|
for line in self.lines.iter() {
|
||||||
contents.extend(line.assemble(session)?);
|
contents.extend(line.assemble(session)?);
|
||||||
session.pos += line.len();
|
session.pos += line.len();
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
contents.len() as u64,
|
contents.len() as u64,
|
||||||
section_len,
|
content_len,
|
||||||
"in section {}",
|
"in section {}",
|
||||||
self.name
|
self.name
|
||||||
);
|
);
|
||||||
@@ -90,7 +91,7 @@ impl Asm for DataSection {
|
|||||||
Ok(obj::DataSection {
|
Ok(obj::DataSection {
|
||||||
name: self.name.clone(),
|
name: self.name.clone(),
|
||||||
start,
|
start,
|
||||||
len: section_len,
|
len: content_len,
|
||||||
contents,
|
contents,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ pub enum AsmError {
|
|||||||
section_size
|
section_size
|
||||||
))]
|
))]
|
||||||
SectionTooShort {
|
SectionTooShort {
|
||||||
|
name: String,
|
||||||
section_end: u64,
|
section_end: u64,
|
||||||
section_size: u64,
|
section_size: u64,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::{addr::*, error::*, flags::*, inst::*, mem::*, obj::obj::*, reg::*};
|
use crate::{addr::*, error::*, flags::*, inst::*, interrupt::*, mem::*, obj::obj::*, reg::*};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
regs: [u64; NUM_REGS],
|
regs: [u64; NUM_REGS],
|
||||||
@@ -47,6 +48,10 @@ impl State {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Memory
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub fn mem_cursor(&self, addr: Addr) -> MemCursor<&[u8]> {
|
pub fn mem_cursor(&self, addr: Addr) -> MemCursor<&[u8]> {
|
||||||
let mut cursor = MemCursor::new(self.mem.as_slice());
|
let mut cursor = MemCursor::new(self.mem.as_slice());
|
||||||
cursor.set_position(addr);
|
cursor.set_position(addr);
|
||||||
@@ -131,6 +136,31 @@ impl State {
|
|||||||
self.set_reg_unchecked(FLAGS, flags.bits());
|
self.set_reg_unchecked(FLAGS, flags.bits());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interrupts
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
pub fn ivt(&self) -> Result<&[Interrupt]> {
|
||||||
|
let ivt_addr = self.get_reg_unchecked(IVT);
|
||||||
|
if ivt_addr % 64 != 0 {
|
||||||
|
panic!("illegal IVT address {:#x}; must be divisible by 64", ivt_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = ivt_addr as usize;
|
||||||
|
let end = start + (IVT_LENGTH * mem::size_of::<Interrupt>());
|
||||||
|
|
||||||
|
if end > self.mem.len() {
|
||||||
|
return Err(VmError::MemOutOfBounds { addr: Addr(ivt_addr) });
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is safe because we check the bounds above
|
||||||
|
let slice_ptr = (&self.mem[start..]).as_ptr();
|
||||||
|
let slice = unsafe {
|
||||||
|
std::slice::from_raw_parts(slice_ptr as *const Interrupt, IVT_LENGTH)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(slice)
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Execution
|
// Execution
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
Reference in New Issue
Block a user