Files
8086-rs/src/interpreter/memory.rs

65 lines
2.1 KiB
Rust

use crate::operands::{Byte, ImmediateOperand, Word};
use super::interpreter::InterpreterError;
/// 2*20 = 1MiB
const MEMORY_SIZE: usize = 1048576;
#[derive(Debug, Clone, Copy)]
pub struct Memory {
pub raw: [Byte; MEMORY_SIZE as usize],
}
impl Memory {
pub fn new() -> Self {
Self {
raw: [0; MEMORY_SIZE as usize],
}
}
/// Safely writes a [`ImmediateOperand`] into an index of memory.
/// Warning: Does access at `addr`, not `DS:addr`!
pub fn write_raw(&mut self, addr: Word, val: ImmediateOperand) -> Result<(), InterpreterError> {
match val {
ImmediateOperand::Byte(b) => {
if addr as usize > MEMORY_SIZE {
return Err(InterpreterError::MemoryOutOfBound(addr));
} else {
self.raw[addr as usize] = b;
log::debug!("Wrote raw byte {b:#04x} at addr {addr:#04x}");
}
}
ImmediateOperand::Word(w) => {
if (addr + 1) as usize > MEMORY_SIZE {
return Err(InterpreterError::MemoryOutOfBound(addr));
} else {
let [low, high] = w.to_le_bytes();
self.raw[addr as usize] = low;
self.raw[(addr + 1) as usize] = high;
log::debug!(
"Wrote raw byte {low:#04x} and {high:#04x}, starting at addr {addr:#04x}"
);
}
}
}
Ok(())
}
/// Safely reads a [`Word`] from an index of memory.
/// Warning: Does access at `addr`, not `DS:addr`!
pub fn read_raw(&self, addr: Word) -> Result<Word, InterpreterError> {
let b1 = self
.raw
.get(addr as usize)
.ok_or(InterpreterError::MemoryOutOfBound(addr))?
.to_owned();
let b2 = self
.raw
.get((addr + 1) as usize)
.ok_or(InterpreterError::MemoryOutOfBound(addr))?
.to_owned();
log::debug!("Read raw byte {b1:#04x} and {b2:#04x}, starting at addr {addr:#04x}");
Ok(Word::from_be_bytes([b2, b1]))
}
}