[pcr] address checks in Program counter

This commit is contained in:
2024-02-18 09:57:10 +05:30
parent 2f0228eccb
commit 8df1da1d17
3 changed files with 42 additions and 8 deletions

View File

@@ -2,4 +2,4 @@ pub mod cpu;
pub mod mmu; pub mod mmu;
pub mod ram; pub mod ram;
pub mod iomem; pub mod iomem;
mod program_counter; pub mod program_counter;

View File

@@ -1,27 +1,37 @@
use crate::emu::mmu::Memory; use crate::emu::mmu::{Memory, RAM_MEM_END};
use crate::misc::emulator_error::DeviceType::PC; use crate::misc::emulator_error::DeviceType::PC;
use crate::misc::emulator_error::EmulatorError; use crate::misc::emulator_error::EmulatorError;
use crate::misc::endian::{read_big_endian_u24, write_big_endian_u24}; use crate::misc::endian::{read_big_endian_u24, write_big_endian_u24};
use crate::misc::result::EmulatorResult; use crate::misc::result::EmulatorResult;
#[derive(Debug,Default, Copy, Clone)] #[derive(Debug, Default, Copy, Clone)]
pub struct ProgramCounter { pub struct ProgramCounter {
/// 24bit location register /// 24bit location register
program_counter_register: [u8; 3], program_counter_register: [u8; 3],
} }
impl ProgramCounter { impl ProgramCounter {
pub fn new() -> ProgramCounter {
ProgramCounter {
program_counter_register: [0; 3]
}
}
// get the current program counter as an address // get the current program counter as an address
pub fn get_pc_value(&self) -> u32 { pub fn get_pc_value(&self) -> u32 {
read_big_endian_u24(&self.program_counter_register) read_big_endian_u24(&self.program_counter_register)
} }
// assign a value of PC to start execution // assign a value of PC to start execution
pub fn set_address(&mut self, address: u32) { pub fn set_address(&mut self, address: u32) -> EmulatorResult<()> {
log::debug!("Setting PC as {}",address); log::debug!("Setting PC as {}",address);
write_big_endian_u24(address, &mut self.program_counter_register) if address >= (2 << 24) {
return Err(EmulatorError::UnreachableMemory(PC, address));
}
write_big_endian_u24(address, &mut self.program_counter_register);
Ok(())
} }
} }
/// Allow Using Program counter as mapped memory /// Allow Using Program counter as mapped memory
impl Memory for ProgramCounter { impl Memory for ProgramCounter {
fn try_get_byte(&self, address: u32) -> EmulatorResult<u8> { fn try_get_byte(&self, address: u32) -> EmulatorResult<u8> {
@@ -35,4 +45,27 @@ impl Memory for ProgramCounter {
log::error!("Unsupported Method!"); log::error!("Unsupported Method!");
todo!() todo!()
} }
}
#[cfg(test)]
mod test {
use crate::emu::program_counter::ProgramCounter;
#[test]
pub fn setting_address_works() {
const ADDRESS: u32 = 4;
let mut pc = ProgramCounter::new();
let res = pc.set_address(ADDRESS);
assert!(res.is_ok());
assert_eq!(ADDRESS, pc.get_pc_value());
}
#[test]
pub fn set_invalid_addr_returns_error() {
const ADDRESS: u32 = 2 << 24;
let mut pc = ProgramCounter::new();
let res = pc.set_address(ADDRESS);
assert!(res.is_err());
}
} }

View File

@@ -2,7 +2,8 @@ use simple_logger::SimpleLogger;
use crate::emu::iomem::MemoryMappedIO; use crate::emu::iomem::MemoryMappedIO;
use crate::emu::ram::RamMemory; use crate::emu::ram::RamMemory;
use crate::emu::mmu::{Memory, MappedMemory}; use crate::emu::mmu::{Memory, MappedMemory};
use crate::misc::emulator_error::EmulatorError; use crate::emu::program_counter::ProgramCounter;
use crate::misc::result::EmulatorResult; use crate::misc::result::EmulatorResult;
mod emu; mod emu;
@@ -12,8 +13,8 @@ mod graphics;
fn main() -> EmulatorResult<()> { fn main() -> EmulatorResult<()> {
SimpleLogger::new().env().init().unwrap(); SimpleLogger::new().env().init().unwrap();
let program_counter = ProgramCounter::new();
let mmio = MemoryMappedIO::new(); let mmio = MemoryMappedIO::new(program_counter);
let ram = RamMemory::try_new()?; let ram = RamMemory::try_new()?;
let mmu = MappedMemory::new(mmio, ram); let mmu = MappedMemory::new(mmio, ram);
for i in 0..10 { for i in 0..10 {