diff --git a/src/arm7tdmi.rs b/src/arm7tdmi.rs index 138a2e7b..527aec61 100644 --- a/src/arm7tdmi.rs +++ b/src/arm7tdmi.rs @@ -3,6 +3,8 @@ use std::convert::TryInto; use crate::alu_instruction::ArmModeAluInstruction; use crate::bitwise::Bits; use crate::instruction::ArmModeInstruction; +use crate::internal_memory::InternalMemory; +use crate::io_device::IoDevice; use crate::{condition::Condition, cpsr::Cpsr, cpu::Cpu}; /// Contains the 16 registers for the CPU, latest (R15) is special because @@ -39,6 +41,8 @@ pub struct Arm7tdmi { registers: Registers, cpsr: Cpsr, + + memory: InternalMemory, } const OPCODE_ARM_SIZE: usize = 4; @@ -113,6 +117,7 @@ impl Arm7tdmi { rom, registers: Registers::default(), cpsr: Cpsr::default(), + memory: InternalMemory::new(), } } @@ -225,15 +230,20 @@ impl Arm7tdmi { let load_store: SingleDataTransfer = opcode.try_into().expect("convert to Single Data Transfer"); + let value: u32 = self + .memory + .read_at(if up_down { + address.wrapping_sub(offset) + } else { + address.wrapping_add(offset) + }) + .try_into() + .unwrap(); // FIXME: is this right? Or we should read a WORD (u32) + match load_store { - SingleDataTransfer::Ldr => self.registers.set_register_at( - rd.try_into().unwrap(), - if up_down { - address.wrapping_sub(offset) - } else { - address.wrapping_add(offset) - }, - ), + SingleDataTransfer::Ldr => self + .registers + .set_register_at(rd.try_into().unwrap(), value), _ => todo!(), } } @@ -428,8 +438,11 @@ mod tests { // then will be 92 + 8 (.wrapping_sub(offset)) cpu.registers.set_program_counter(92); + // simulate mem already contains something. + cpu.memory.write_at(76, 99); + cpu.execute(op_code, instruction); - assert_eq!(cpu.registers.register_at(13), 76); + assert_eq!(cpu.registers.register_at(13), 99); assert_eq!(cpu.registers.program_counter(), 96); } } diff --git a/src/bitwise.rs b/src/bitwise.rs index 467413e6..96f6f362 100644 --- a/src/bitwise.rs +++ b/src/bitwise.rs @@ -12,6 +12,7 @@ pub trait Bits { fn get_bit(self, bit_idx: u8) -> bool; fn get_bits(self, bits_range: RangeInclusive) -> u32; fn are_bits_on(self, bits_range: RangeInclusive) -> bool; + fn clear_bits(&mut self, bit_idx: u8, to: u8); } impl Bits for u32 { @@ -82,6 +83,14 @@ impl Bits for u32 { } true } + + /// To clear all bits from the `from` through `to` (inclusive) + fn clear_bits(&mut self, from: u8, to: u8) { + let from_mask = (1 << from) - 1; + let to_mask = (1 << to) - 1; + let mask = !(from_mask - to_mask); + *self &= mask; + } } #[cfg(test)] @@ -89,6 +98,22 @@ mod tests { use super::*; use rand::Rng; + #[test] + fn test_clear_bits_msb_to_idx() { + let mut b = 0b11111111; + b.clear_bits(5, 2); + println!("{}", b); + assert_eq!(b, 0b11100011); + } + + #[test] + fn test_clear_bits_idx_to_0() { + let mut b = 0b11111111; + b.clear_bits(3, 1); + println!("{}", b); + assert_eq!(b, 0b11111001); + } + #[test] fn test_is_on() { let b = 0b110011101_u32; diff --git a/src/internal_memory.rs b/src/internal_memory.rs index cd9df192..81d3b663 100644 --- a/src/internal_memory.rs +++ b/src/internal_memory.rs @@ -6,7 +6,7 @@ pub struct InternalMemory { } impl InternalMemory { - pub fn new() -> Self { + pub const fn new() -> Self { Self { internal_work_ram: [0; 0x7FFF], } diff --git a/src/main.rs b/src/main.rs index 7757ffd7..4867ad68 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,8 @@ mod cpsr; mod cpu; mod egui_app; mod instruction; +mod internal_memory; +mod io_device; mod ppu; fn main() {