aboutsummaryrefslogtreecommitdiff
path: root/src/system.rs
blob: faadb133a15b55dbb89b21a063407b3387568f30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use std;

use rustv::isa;
use rustv::memory::SharedMemory;
use rustv::register_file::RegisterFile;
use rustv::syscall;
use rustv::trap::Trap;

pub struct SyscallHandler<'a> {
    memory: SharedMemory<'a>,
}

impl<'a> SyscallHandler<'a> {
    pub fn new(memory: SharedMemory<'a>) -> SyscallHandler<'a> {
        SyscallHandler {
            memory: memory
        }
    }
}

impl<'a> SyscallHandler<'a> {
    fn print(&mut self, registers: &mut RegisterFile) -> Option<Trap> {
        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(0x00) = c {
                break;
            }
            else if let Ok(c) = c {
                string.push(c);
            }

            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

    }
}

impl<'a> syscall::SyscallHandler for SyscallHandler<'a> {
    // TODO: is trap really appropriate here?
    fn syscall(&mut self, registers: &mut RegisterFile) -> Option<Trap> {
        let syscall_number = registers.read_word(isa::Register::X10);

        match syscall_number {
            22 => {
                self.print(registers)
            }

            _ => {
                // TODO: some sort of error reporting
                None
            }
        }
    }
}