progress: new assembler works, instruction set fully implemented with call/ret and push/pop, bf.dsa works which means the dsa assembly language works reliably. still a few bugs to fix. might be able to squeeze out a tiny bit more performance
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
use std::{
|
||||
alloc::{Layout, alloc_zeroed},
|
||||
hint::{likely, unlikely},
|
||||
};
|
||||
|
||||
use crate::memory::{
|
||||
PhysAddr, RandomAccessMemory,
|
||||
ram::{NUM_PAGES, Page, idx},
|
||||
};
|
||||
|
||||
pub struct StackArrayStore {
|
||||
pages: [*mut Page; NUM_PAGES],
|
||||
}
|
||||
|
||||
unsafe impl Send for StackArrayStore {}
|
||||
impl StackArrayStore {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pages: [0 as *mut Page; 2 << 20],
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc(&mut self) -> *mut Page {
|
||||
let layout = Layout::from_size_align(4096, 4096).unwrap();
|
||||
unsafe { alloc_zeroed(layout) as *mut Page }
|
||||
}
|
||||
}
|
||||
|
||||
impl RandomAccessMemory for StackArrayStore {
|
||||
#[inline(always)]
|
||||
fn read_word(&self, addr: PhysAddr) -> u32 {
|
||||
debug_assert_eq!(addr % 4, 0);
|
||||
let (idx, offset) = idx(addr);
|
||||
|
||||
if likely(!self.pages[idx].is_null()) {
|
||||
return unsafe { (self.pages[idx] as *const u32).byte_add(offset).read() };
|
||||
}
|
||||
|
||||
// Slow path: MMIO, fault, etc — never inlined
|
||||
// Since we're only reading, we can safely return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn read_byte(&self, addr: PhysAddr) -> u8 {
|
||||
let (idx, offset) = idx(addr);
|
||||
|
||||
if likely(!self.pages[idx].is_null()) {
|
||||
return unsafe { (self.pages[idx] as *const u8).byte_add(offset).read() };
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn read_page(&self, addr: PhysAddr) -> &Page {
|
||||
debug_assert_eq!(addr % 4096, 0);
|
||||
let (idx, _) = idx(addr);
|
||||
|
||||
if likely(!self.pages[idx].is_null()) {
|
||||
return unsafe { &*(self.pages[idx] as *const Page) };
|
||||
}
|
||||
|
||||
return &Page::ZERO;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn write_byte(&mut self, addr: PhysAddr, value: u8) {
|
||||
let (idx, offset) = idx(addr);
|
||||
|
||||
if unlikely(self.pages[idx].is_null()) {
|
||||
self.pages[idx] = self.alloc();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
(self.pages[idx] as *mut u8).byte_add(offset).write(value);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn write_word(&mut self, addr: PhysAddr, value: u32) {
|
||||
debug_assert_eq!(addr % 4, 0);
|
||||
let (idx, offset) = idx(addr);
|
||||
|
||||
if unlikely(self.pages[idx].is_null()) {
|
||||
self.pages[idx] = self.alloc();
|
||||
}
|
||||
|
||||
unsafe { (self.pages[idx] as *mut u32).byte_add(offset).write(value) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn write_page(&mut self, addr: PhysAddr, value: &Page) {
|
||||
debug_assert_eq!(addr % 4096, 0);
|
||||
let (idx, _) = idx(addr);
|
||||
|
||||
if unlikely(self.pages[idx].is_null()) {
|
||||
self.pages[idx] = self.alloc();
|
||||
}
|
||||
|
||||
unsafe { (self.pages[idx] as *mut Page).copy_from(value, 1) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user