Skip to content

Commit 30fb6d6

Browse files
committed
Add back mmu
* Speed up some hot paths
1 parent 94327cc commit 30fb6d6

File tree

7 files changed

+191
-84
lines changed

7 files changed

+191
-84
lines changed

src/cartridge_io.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@ use crate::cartridge_metadata::get_cartridge_metadata;
22
use crate::logging::debug_println;
33
use crate::mmap::PAGE_SIZE;
44
use crate::utils;
5-
use crate::utils::{rgb5_to_rgb8, NoHashMap};
5+
use crate::utils::{rgb5_to_rgb8, HeapMemU8, NoHashMap};
66
use static_assertions::const_assert_eq;
7-
use std::cell::RefCell;
7+
use std::cell::UnsafeCell;
88
use std::cmp::min;
99
use std::fs::File;
1010
use std::io::{ErrorKind, Read, Seek};
1111
use std::ops::{Deref, DerefMut};
1212
use std::os::unix::fs::FileExt;
1313
use std::path::PathBuf;
14-
use std::rc::Rc;
1514
use std::sync::{Arc, Mutex};
1615
use std::time::Instant;
1716
use std::{io, mem};
@@ -85,7 +84,7 @@ pub struct CartridgeIo {
8584
pub file_name: String,
8685
pub file_size: u32,
8786
pub header: CartridgeHeader,
88-
content_pages: RefCell<NoHashMap<u32, Rc<[u8; PAGE_SIZE]>>>,
87+
content_pages: UnsafeCell<NoHashMap<u32, HeapMemU8<{ PAGE_SIZE * 4 }>>>,
8988
save_file_path: PathBuf,
9089
pub save_file_size: u32,
9190
save_buf: Mutex<(Vec<u8>, bool)>,
@@ -130,31 +129,31 @@ impl CartridgeIo {
130129
file_name: file_path.file_name().unwrap().to_str().unwrap().to_string(),
131130
file_size,
132131
header,
133-
content_pages: RefCell::new(NoHashMap::default()),
132+
content_pages: UnsafeCell::new(NoHashMap::default()),
134133
save_file_path,
135134
save_file_size,
136135
save_buf: Mutex::new((save_buf, false)),
137136
})
138137
}
139138

140-
fn get_page(&self, page_addr: u32) -> io::Result<Rc<[u8; PAGE_SIZE]>> {
141-
debug_assert_eq!(page_addr & (PAGE_SIZE as u32 - 1), 0);
142-
let mut pages = self.content_pages.borrow_mut();
139+
fn get_page(&self, page_addr: u32) -> io::Result<*const [u8; PAGE_SIZE * 4]> {
140+
debug_assert_eq!(page_addr & ((PAGE_SIZE * 4) as u32 - 1), 0);
141+
let pages = unsafe { self.content_pages.get().as_mut_unchecked() };
143142
match pages.get(&page_addr) {
144143
None => {
145-
// exceeds 4MB
146-
if pages.len() >= 1024 {
144+
// exceeds 8MB
145+
if pages.len() >= 512 {
147146
debug_println!("clear cartridge pages");
148147
pages.clear();
149148
}
150149

151-
let mut buf = [0u8; PAGE_SIZE];
152-
self.file.read_at(&mut buf, page_addr as u64)?;
153-
let buf = Rc::new(buf);
154-
pages.insert(page_addr, buf.clone());
155-
Ok(buf)
150+
let mut buf = HeapMemU8::new();
151+
let ptr = buf.as_ptr();
152+
self.file.read_at(buf.as_mut(), page_addr as u64)?;
153+
pages.insert(page_addr, buf);
154+
Ok(ptr as _)
156155
}
157-
Some(page) => Ok(page.clone()),
156+
Some(page) => Ok(page.as_ptr() as _),
158157
}
159158
}
160159

@@ -163,13 +162,14 @@ impl CartridgeIo {
163162
while remaining > 0 {
164163
let slice_start = slice.len() - remaining;
165164

166-
let page_addr = (offset + slice_start as u32) & !(PAGE_SIZE as u32 - 1);
165+
let page_addr = (offset + slice_start as u32) & !((PAGE_SIZE * 4) as u32 - 1);
167166
let page_offset = offset + slice_start as u32 - page_addr;
168167
let page = match self.get_page(page_addr) {
169168
Ok(page) => page,
170169
Err(err) => return Err(err),
171170
};
172-
let page_slice = &page.as_slice()[page_offset as usize..];
171+
let page = unsafe { page.as_ref().unwrap_unchecked() };
172+
let page_slice = &page[page_offset as usize..];
173173

174174
let read_amount = min(remaining, page_slice.len());
175175
let slice_end = slice_start + read_amount;

src/core/memory/mem.rs

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::core::cp15::TcmState;
22
use crate::core::emu::{get_cp15, Emu};
33
use crate::core::memory::io_arm7::IoArm7;
44
use crate::core::memory::io_arm9::IoArm9;
5-
use crate::core::memory::mmu::{MmuArm7, MmuArm9};
5+
use crate::core::memory::mmu::{MmuArm7, MmuArm9, MMU_PAGE_SHIFT};
66
use crate::core::memory::oam::Oam;
77
use crate::core::memory::palettes::Palettes;
88
use crate::core::memory::regions;
@@ -15,7 +15,8 @@ use crate::jit::jit_memory::{JitMemory, JitRegion};
1515
use crate::logging::debug_println;
1616
use crate::mmap::Shm;
1717
use crate::utils::Convert;
18-
use std::intrinsics::unlikely;
18+
use std::hint::unreachable_unchecked;
19+
use std::intrinsics::{likely, unlikely};
1920
use std::sync::atomic::AtomicU16;
2021
use std::sync::Arc;
2122
use CpuType::ARM7;
@@ -71,47 +72,27 @@ impl Memory {
7172
pub fn read_with_options<const CPU: CpuType, const TCM: bool, T: Convert>(&mut self, addr: u32, emu: &mut Emu) -> T {
7273
debug_println!("{:?} memory read at {:x}", CPU, addr);
7374
let aligned_addr = addr & !(size_of::<T>() as u32 - 1);
75+
let aligned_addr = aligned_addr & 0x0FFFFFFF;
7476

75-
let addr_base = aligned_addr & 0x0F000000;
76-
let addr_offset = aligned_addr & !0xFF000000;
77-
78-
let vmem = {
77+
let (vmem, mmu) = {
7978
let mmu = get_mem_mmu!(self, CPU);
8079
if CPU == ARM9 && TCM {
81-
mmu.get_base_tcm_ptr()
80+
(mmu.get_base_tcm_ptr(), mmu.get_mmu_read_tcm())
8281
} else {
83-
mmu.get_base_ptr()
82+
(mmu.get_base_ptr(), mmu.get_mmu_read())
8483
}
8584
};
8685

87-
if CPU == ARM9 && TCM {
88-
let cp15 = get_cp15!(emu, ARM9);
89-
if unlikely(aligned_addr >= cp15.dtcm_addr && aligned_addr < cp15.dtcm_addr + cp15.dtcm_size && cp15.dtcm_state == TcmState::RW) {
90-
let ret = unsafe { (vmem.add(aligned_addr as usize) as *const T).read() };
91-
debug_println!("{:?} dtcm read at {:x} with value {:x}", CPU, aligned_addr, ret.into());
92-
return ret;
93-
}
86+
let mapped = unsafe { *mmu.get_unchecked((aligned_addr as usize) >> MMU_PAGE_SHIFT) };
87+
if likely(mapped) {
88+
return unsafe { (vmem.add(aligned_addr as usize) as *const T).read() };
9489
}
9590

91+
let addr_base = aligned_addr & 0x0F000000;
92+
let addr_offset = aligned_addr & !0xFF000000;
93+
9694
let ret = match addr_base {
97-
regions::ITCM_OFFSET | regions::ITCM_OFFSET2 => match CPU {
98-
ARM9 => {
99-
let mut ret = T::from(0);
100-
if TCM {
101-
let cp15 = get_cp15!(emu, ARM9);
102-
if aligned_addr < cp15.itcm_size && cp15.itcm_state == TcmState::RW {
103-
debug_println!("{:?} itcm read at {:x}", CPU, aligned_addr);
104-
ret = unsafe { (vmem.add(aligned_addr as usize) as *const T).read() }
105-
}
106-
}
107-
ret
108-
}
109-
// Bios of arm7 has same offset as itcm on arm9
110-
ARM7 => unsafe { (vmem.add(aligned_addr as usize) as *const T).read() },
111-
},
112-
regions::MAIN_OFFSET | regions::SHARED_WRAM_OFFSET | regions::GBA_ROM_OFFSET | regions::GBA_ROM_OFFSET2 | 0x0F000000 => unsafe {
113-
(vmem.add((aligned_addr & 0x0FFFFFFF) as usize) as *const T).read()
114-
},
95+
regions::ITCM_OFFSET | regions::ITCM_OFFSET2 => T::from(0),
11596
regions::IO_PORTS_OFFSET => match CPU {
11697
ARM9 => self.io_arm9.read(addr_offset, emu),
11798
ARM7 => {
@@ -130,8 +111,7 @@ impl Memory {
130111
regions::STANDARD_PALETTES_OFFSET => self.palettes.read(addr_offset),
131112
regions::VRAM_OFFSET => self.vram.read::<CPU, _>(addr_offset),
132113
regions::OAM_OFFSET => self.oam.read(addr_offset),
133-
regions::GBA_RAM_OFFSET => T::from(0xFFFFFFFF),
134-
_ => unreachable!(),
114+
_ => unsafe { unreachable_unchecked() },
135115
};
136116

137117
debug_println!("{:?} memory read at {:x} with value {:x}", CPU, addr, ret.into());
@@ -223,7 +203,7 @@ impl Memory {
223203
}
224204
regions::OAM_OFFSET => self.oam.write(addr_offset, value),
225205
regions::GBA_ROM_OFFSET => {}
226-
_ => unreachable!(),
206+
_ => unsafe { unreachable_unchecked() },
227207
};
228208
}
229209
}

0 commit comments

Comments
 (0)