fix(interpreter): always read word from memory

It's not possible to know if a word or byte is requested, or rather
it would be a pain to retrieve that information.
It is much easier to just read a full word and then discard the top
half, if just a byte is needed.
This commit is contained in:
2025-06-17 12:00:56 +09:00
parent 200640447b
commit 7f4d79d840
2 changed files with 34 additions and 57 deletions

View File

@@ -48,60 +48,37 @@ impl Memory {
idx: MemoryIndex,
val: ImmediateOperand,
) {
match Memory::calc_memidx(regs, idx) {
ImmediateOperand::Byte(idx_byte) => match val {
ImmediateOperand::Byte(value) => {
log::debug!("Writing byte {value:#04x} to memory location {idx_byte:#04x}");
self.memory[idx_byte as usize] = value
}
ImmediateOperand::Word(_) => panic!("Cannot add Word to Byte Memory Index"),
},
ImmediateOperand::Word(idx_word) => match val {
ImmediateOperand::Word(value) => {
let byte1 = idx_word / 2;
let byte2 = idx_word / 2 + 1;
let [low, high]: [u8; 2] = value.to_le_bytes();
log::debug!(
"Writing bytes {low:#04x} and {high:#04x} to memory location {byte1:#04x} and {byte2:#04x}"
);
self.memory[byte1 as usize] = low;
self.memory[byte1 as usize] = high;
}
ImmediateOperand::Byte(value) => {
self.memory[(idx_word * 2) as usize] = value;
}
},
let idx = Memory::calc_memidx(regs, idx);
match val {
ImmediateOperand::Byte(b) => {
log::debug!("Writing byte {b:#04x} to memory location {idx:#04x}");
self.memory[idx as usize] = b
}
ImmediateOperand::Word(value) => {
let byte1 = idx / 2;
let byte2 = idx / 2 + 1;
let [low, high]: [u8; 2] = value.to_le_bytes();
log::debug!(
"Writing bytes {low:#04x} and {high:#04x} to memory location {byte1:#04x} and {byte2:#04x}"
);
self.memory[byte1 as usize] = low;
self.memory[byte1 as usize] = high;
}
}
}
/// Read into memory with a [`MemoryIndex`] as index.
pub fn read(
&self,
regs: &crate::interpreter::register::Register,
idx: MemoryIndex,
) -> ImmediateOperand {
match Memory::calc_memidx(regs, idx) {
ImmediateOperand::Byte(byte) => {
log::debug!("Reading byte {byte:#04x} from memory");
ImmediateOperand::Byte(self.memory[byte as usize])
}
ImmediateOperand::Word(word) => {
let byte1 = word / 2;
let byte2 = word / 2 + 1;
log::debug!("Reading bytes {byte1:#04x} and {byte2:#04x} from memory");
ImmediateOperand::Word(Word::from_le_bytes([
self.memory[byte1 as usize],
self.memory[byte2 as usize],
]))
}
}
/// Always reads a whole word.
pub fn read(&self, regs: &crate::interpreter::register::Register, idx: MemoryIndex) -> Word {
let idx = Self::calc_memidx(regs, idx);
let byte1 = idx / 2;
let byte2 = idx / 2 + 1;
log::debug!("Reading bytes {byte1:#04x} and {byte2:#04x} from memory");
Word::from_le_bytes([self.memory[byte1 as usize], self.memory[byte2 as usize]])
}
/// Calculate the absolute memory address from a [`MemoryIndex`] struct.
pub fn calc_memidx(
regs: &crate::interpreter::register::Register,
idx: MemoryIndex,
) -> ImmediateOperand {
pub fn calc_memidx(regs: &crate::interpreter::register::Register, idx: MemoryIndex) -> Word {
let mut base = ImmediateOperand::Word(0);
let mut index = ImmediateOperand::Word(0);
let mut disp = Displacement::IWord(0);
@@ -116,6 +93,6 @@ impl Memory {
disp = displacement;
}
base + index + disp
(base + index + disp).into()
}
}