use std; use std::cell::RefCell; use std::rc::Rc; use rustv::isa; use rustv::memory::{MemoryInterface, Mmu}; use rustv::register_file::RegisterFile; use rustv::syscall; use rustv::trap::Trap; use memory_tracker::MemoryTracker; use shareable_cache::ShareableCache; pub struct SyscallHandler<'a> { memory: Rc>, caches: Vec>>>, } impl<'a> SyscallHandler<'a> { pub fn new(memory: Rc>, caches: Vec>>>) -> SyscallHandler<'a> { SyscallHandler { memory: memory, caches: caches, } } } impl<'a> SyscallHandler<'a> { fn prints(&mut self, registers: &mut RegisterFile) -> Option { let mut base = registers.read_word(isa::Register::X11); let mut string = vec![]; loop { let c = self.memory.borrow_mut().read_byte(base); if let Ok(isa::Byte(0x00)) = c { break; } else if let Ok(c) = c { string.push(c.0); } base += 1; } let result = std::str::from_utf8(&string); if let Ok(string) = result { println!("{}", string); } else { println!("Error printing string: not valid UTF-8: {:?}", result); } None } fn printi(&mut self, registers: &mut RegisterFile) -> Option { println!("{}", registers.read_word(isa::Register::X11)); None } fn enable_secondary(&mut self, core_id: usize) -> Option { debug!("[syscall] [memory] Secondary cache enabled for core {}", core_id); self.caches[core_id].borrow_mut().enable_secondary(); None } fn disable_secondary(&mut self, core_id: usize) -> Option { debug!("[syscall] [memory] Secondary cache disabled for core {}", core_id); self.caches[core_id].borrow_mut().disable_secondary(); None } } impl<'a> syscall::SyscallHandler for SyscallHandler<'a> { // TODO: is trap really appropriate here? fn syscall(&mut self, core_id: usize, registers: &mut RegisterFile, mmu: &Mmu) -> Option { let syscall_number = registers.read_word(isa::Register::X10); match syscall_number.0 { 22 => self.prints(registers), 23 => self.printi(registers), 24 => self.enable_secondary(core_id), 25 => self.disable_secondary(core_id), _ => { // TODO: some sort of error reporting None } } } fn should_halt(&self) -> bool { let (p1, p2) = self.memory.borrow().score(); (p1 >= 0x1000000) || (p2 >= 0x1000000) } }