riscii

An emulator for the RISC II
Log | Files | Refs | LICENSE

commit 528a2619207271d315330e34958f280110f0e84f
parent 1f5de190da64b59496c50a2c9a2f69b825cc78b6
Author: Ryan Jeffrey <ryan@ryanmj.xyz>
Date:   Fri, 10 Jun 2022 16:39:20 -0700

Fix compile errors

Diffstat:
Msrc/config.rs | 7+++++++
Msrc/decode.rs | 3+++
Msrc/main.rs | 27++++++++++++++++++++++++++-
Msrc/memory.rs | 12+++++++-----
Msrc/register.rs | 64+++++++++++++++++++++++++++++++---------------------------------
Msrc/util.rs | 12++++++------
6 files changed, 80 insertions(+), 45 deletions(-)

diff --git a/src/config.rs b/src/config.rs @@ -149,6 +149,7 @@ impl Config { self.cache_path = args_get_next_arg(&args, i, &format!("cache_path"))?.clone(); skips += 1; } + // Skip this argument since it is special. "--config_path" => { args_get_next_arg(&args, i, &format!("config_path"))?; skips += 1; @@ -177,6 +178,8 @@ impl Config { Ok(()) } + // Getters. + pub fn get_win_width(&self) -> u32 { self.win_width } @@ -184,6 +187,10 @@ impl Config { pub fn get_win_height(&self) -> u32 { self.win_height } + + pub fn get_mem_size(&self) -> u32 { + self.mem + } } // Local functions. diff --git a/src/decode.rs b/src/decode.rs @@ -215,6 +215,7 @@ pub enum Instruction { Strb(bool, u8, u32), } +/// Opcode errors. pub enum DecodeError { /// Indicates an invalid instruction. The first u32 indicates which bits are invalid, /// the final u32 is the whole opcode. @@ -250,6 +251,8 @@ fn get_cond_from_opcode(opcode: u32) -> Result<Conditional, DecodeError> { }) } +// Public function declarations. + pub fn decode(opcode: u32) -> Result<Instruction, DecodeError> { type I = Instruction; // SCC flag (<24>). diff --git a/src/main.rs b/src/main.rs @@ -20,12 +20,25 @@ mod main_test; mod config; mod decode; +mod memory; +mod register; mod sdl; mod util; use decode::decode_file; use std::fs; +use config::Config; +use memory::Memory; +use register::State; + +// Struct/enum declarations. + +struct System { + regs: register::State, + mem: memory::Memory, +} + fn get_program(path: &String) -> Result<Vec<u8>, String> { println!("Opening binary file {}.", path); @@ -36,9 +49,10 @@ fn get_program(path: &String) -> Result<Vec<u8>, String> { } fn main() -> Result<(), String> { - let config = config::Config::init()?; + let config = Config::init()?; let context = sdl::Context::new(&config)?; + let system = System::new(&config); println!( "Running emulator with the following configuration: \n{}\n", config @@ -47,3 +61,14 @@ fn main() -> Result<(), String> { Ok(()) } + +// Impls. + +impl System { + pub fn new(config: &Config) -> Result<Self, String> { + Ok(Self { + regs: State::new(), + mem: Memory::new(config), + }) + } +} diff --git a/src/memory.rs b/src/memory.rs @@ -17,8 +17,10 @@ use util::File; +use config::Config; + /// The real memory of the RISC II emulator. -struct Memory(Vec<u8>); +pub struct Memory(Vec<u8>); // Struct impls. @@ -29,15 +31,15 @@ impl Memory { /// the memory object. pub fn new(config: &Config) -> Self { Self { - 0: vec![0u8; config.mem], + 0: vec![0u8; config.get_mem_size() as usize], } } - pub fn from_vec(memory: &Vec<u8>) { - Self { 0: memory } + pub fn from_vec(memory: &Vec<u8>) -> Self { + Self { 0: memory.clone() } } - fn write_to_file(&mut self, file: &mut File) -> Result<(), String> { + pub fn write_to_file(&mut self, file: &mut File) -> Result<(), String> { file.write_vec(&self.0)?; Ok(()) } diff --git a/src/register.rs b/src/register.rs @@ -12,6 +12,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. +use std::convert::TryInto; /// The number of register window_regs the RISCII supports. pub const NUM_WINDOW_REGS: usize = 6; @@ -36,10 +37,11 @@ pub const SIZEOF_STATE: usize = TOTAL_NUM_REGISTERS * 4; // Struct definitions. /// A RISC II 32bit register. -struct Register(u32); +type Register = u32; /// The CPU's register state. -struct State { +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct State { /// Current window pointer, index of the currently active window. cwp: Register, /// Saved window pointer, the index of the youngest window saved in memory. @@ -80,7 +82,7 @@ impl State { swp: u32::from_be_bytes(buf[4..8].try_into().unwrap()), globals: { let mut result = [0u32; NUM_GLOBALS]; - for _ in NUM_GLOBALS { + for i in 0..result.len() { result[i] = u32::from_be_bytes(buf[cur_offset..cur_offset + 4].try_into().unwrap()); cur_offset += 4; @@ -89,7 +91,7 @@ impl State { }, window_regs: { let mut result = [0u32; NUM_WINDOW_REGISTERS]; - for _ in NUM_WINDOW_REGISTERS { + for i in 0..result.len() { result[i] = u32::from_be_bytes(buf[cur_offset..cur_offset + 4].try_into().unwrap()); cur_offset += 4; @@ -99,37 +101,33 @@ impl State { } } - fn to_buf(&self) -> [u8; SIZEOF_STATE] { - let mut result: [u8; SIZEOF_STATE] = [ - self.cwp.to_be_bytes(), - self.swp.to_be_bytes(), - { - let mut tmp = [u8; NUM_GLOBALS * 4]; - for i in NUM_GLOBALS { - let bytes = self.globals[i].to_be_bytes(); - tmp[i] = bytes[0]; - tmp[i + 1] = bytes[1]; - tmp[i + 1] = bytes[2]; - tmp[i + 1] = bytes[3]; - } - tmp - }, - { - let mut tmp = [u8; NUM_WINDOW_REGISTERS * 4]; - for i in NUM_WINDOW_REGISTERS { - let bytes = self.window_regs[i].to_be_bytes(); - tmp[i] = bytes[0]; - tmp[i + 1] = bytes[1]; - tmp[i + 1] = bytes[2]; - tmp[i + 1] = bytes[3]; - } - tmp - }, - ]; + pub fn to_buf(&self) -> [u8; SIZEOF_STATE] { + let mut result = [0u8; SIZEOF_STATE]; + result[0..4].copy_from_slice(&self.cwp.to_be_bytes()); + result[4..8].copy_from_slice(&self.swp.to_be_bytes()); + let globals = { + let mut tmp = [0u8; NUM_GLOBALS * 4]; + for i in 0..NUM_GLOBALS { + tmp[i * 4..i * 4 + 4].copy_from_slice(&self.globals[i].to_be_bytes()); + } + tmp + }; + + const GLOBAL_OFFSET: usize = 8 + NUM_GLOBALS * 4; + result[8..GLOBAL_OFFSET].copy_from_slice(&globals); + let win_regs = { + let mut tmp = [0u8; NUM_WINDOW_REGISTERS * 4]; + for i in 0..NUM_WINDOW_REGISTERS { + tmp[i * 4..i * 4 + 4].copy_from_slice(&self.window_regs[i].to_be_bytes()); + } + tmp + }; + + result[GLOBAL_OFFSET..].copy_from_slice(&win_regs); result } - fn push_reg_window(&mut self) { + pub fn push_reg_window(&mut self) { self.cwp += 1; while self.cwp >= self.swp { // TODO save the top window_regs into memory. @@ -137,7 +135,7 @@ impl State { } } - fn pop_reg_window(&mut self) { + pub fn pop_reg_window(&mut self) { self.cwp -= 1; while self.swp >= self.cwp { // TODO load window_regs from memory. diff --git a/src/util.rs b/src/util.rs @@ -104,14 +104,14 @@ impl File { } } - fn read_into_vec(&mut self, buf: &mut Vec<u8>) -> Result<(), String> { + pub fn read_into_vec(&mut self, buf: &mut Vec<u8>) -> Result<(), String> { match self.file.read_exact(&mut buf[..]) { Ok(r) => Ok(()), Err(e) => Err(format!("Failed to read file {}, {}", self.path, e)), } } - fn read_file(&mut self) -> Result<Vec<u8>, String> { + pub fn read_file(&mut self) -> Result<Vec<u8>, String> { let metadata = self.get_metadata()?; let mut result = vec![0u8; metadata.len() as usize]; self.read_into_vec(&mut result)?; @@ -119,21 +119,21 @@ impl File { Ok(result) } - fn get_metadata(&mut self) -> Result<Metadata, String> { + pub fn get_metadata(&mut self) -> Result<Metadata, String> { match self.file.metadata() { Ok(r) => Ok(r), Err(e) => Err(format!("Could not read metadata for {}: {}", self.path, e)), } } - fn read(&mut self, buf: &mut [u8]) -> Result<(), String> { + pub fn read(&mut self, buf: &mut [u8]) -> Result<(), String> { match self.file.read_exact(buf) { Ok(r) => Ok(()), Err(e) => Err(format!("Could not read buffer from {}: {}", self.path, e)), } } - fn write_buf(&mut self, buf: &[u8]) -> Result<(), String> { + pub fn write_buf(&mut self, buf: &[u8]) -> Result<(), String> { match self.file.write_all(buf) { Ok(r) => Ok(()), Err(e) => Err(format!( @@ -143,7 +143,7 @@ impl File { } } - fn write_vec(&mut self, buf: &Vec<u8>) -> Result<(), String> { + pub fn write_vec(&mut self, buf: &Vec<u8>) -> Result<(), String> { match self.file.write_all(&buf[..]) { Ok(r) => Ok(()), Err(e) => Err(format!(