Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak committed Jan 17, 2025
1 parent 3a9404c commit f578dd4
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 103 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ opt-level = 3
overflow-checks = true
debug-assertions = true
debug = true
panic = "abort"

[profile.release.package."*"]
opt-level = 3
Expand Down
20 changes: 7 additions & 13 deletions src/core/memory/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::core::memory::wram::Wram;
use crate::core::spu::SoundSampler;
use crate::core::CpuType;
use crate::core::CpuType::ARM9;
use crate::jit::jit_memory::{JitMemory, JitRegion};
use crate::jit::jit_memory::JitMemory;
use crate::logging::debug_println;
use crate::mmap::Shm;
use crate::utils;
Expand Down Expand Up @@ -182,7 +182,7 @@ macro_rules! write_itcm {
let $shm_offset = regions::ITCM_REGION.shm_offset as u32 + ($addr & (regions::ITCM_SIZE - 1));
let $mem = get_mem_mut!($emu);
$write;
get_jit_mut!($emu).invalidate_block::<{ JitRegion::Itcm }>($addr, $size);
get_jit_mut!($emu).invalidate_block($addr, $size);
}
}
}};
Expand All @@ -193,7 +193,7 @@ macro_rules! write_main {
let $shm_offset = regions::MAIN_REGION.shm_offset as u32 + ($addr & (regions::MAIN_SIZE - 1));
let $mem = get_mem_mut!($emu);
$write;
get_jit_mut!($emu).invalidate_block::<{ JitRegion::Main }>($addr, $size);
get_jit_mut!($emu).invalidate_block($addr, $size);
}};
}

Expand All @@ -203,7 +203,7 @@ macro_rules! write_wram {
let $shm_offset = $mem.wram.get_shm_offset::<{ $cpu }>($addr) as u32;
$write;
if $cpu == ARM7 {
get_jit_mut!($emu).invalidate_block::<{ JitRegion::Wram }>($addr, $size);
get_jit_mut!($emu).invalidate_block($addr, $size);
}
}};
}
Expand Down Expand Up @@ -234,9 +234,7 @@ macro_rules! write_vram {
($addr:expr, $size:expr, $emu:expr, $mem:ident, $write:block) => {
let $mem = get_mem_mut!($emu);
$write;
if CPU == ARM7 {
get_jit_mut!($emu).invalidate_block::<{ JitRegion::VramArm7 }>($addr, $size);
}
get_jit_mut!($emu).invalidate_block($addr, $size);
};
}

Expand Down Expand Up @@ -566,9 +564,7 @@ impl<const CPU: CpuType, T: Convert, F: FnMut() -> T> MemoryWriteMultipleIo<CPU,
for i in 0..size {
mem.vram.write::<CPU, _>(addr + (i << write_shift) as u32, read_value());
}
if CPU == ARM7 {
mem.jit.invalidate_block::<{ JitRegion::VramArm7 }>(addr, size << write_shift);
}
mem.jit.invalidate_block(addr, size << write_shift);
}

fn write_oam(addr: u32, size: usize, mut read_value: F, emu: &mut Emu) {
Expand Down Expand Up @@ -731,9 +727,7 @@ impl<const CPU: CpuType, const TCM: bool, T: Convert> MemoryMultipleSliceIo<CPU,
fn write_vram(addr: u32, slice: &[T], emu: &mut Emu) {
let mem = get_mem_mut!(emu);
mem.vram.write_slice::<CPU, _>(addr, slice);
if CPU == ARM7 {
mem.jit.invalidate_block::<{ JitRegion::VramArm7 }>(addr, size_of_val(slice));
}
mem.jit.invalidate_block(addr, size_of_val(slice));
}

fn write_oam(addr: u32, slice: &[T], emu: &mut Emu) {
Expand Down
21 changes: 10 additions & 11 deletions src/core/memory/mmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ pub trait Mmu {
fn remove_write(&self, addr: u32, region: &MemRegion);
}

fn remove_mmu_entry(addr: u32, region: &MemRegion, mmu: &mut [usize]) {
fn remove_mmu_write_entry(addr: u32, region: &MemRegion, mmu: &mut [usize], vmem: &mut VirtualMem) {
// if mmu[(addr >> MMU_PAGE_SHIFT) as usize] == 0 {
// return;
// }
let base_offset = addr - region.start as u32;
let base_offset = base_offset & (region.size as u32 - 1);
for addr_offset in (region.start as u32 + base_offset..region.end as u32).step_by(region.size) {
mmu[(addr_offset >> MMU_PAGE_SHIFT) as usize] = 0;
}
vmem.set_region_protection(addr as usize, MMU_PAGE_SIZE, region, true, false, false);
}

struct MmuArm9Inner {
Expand Down Expand Up @@ -300,12 +304,9 @@ impl Mmu for MmuArm9 {
}

fn remove_write(&self, addr: u32, region: &MemRegion) {
unsafe {
let mmu = (*self.inner.get()).mmu_write.as_mut();
remove_mmu_entry(addr, region, mmu);
let mmu = (*self.inner.get()).mmu_write_tcm.as_mut();
remove_mmu_entry(addr, region, mmu);
}
let inner = unsafe { self.inner.get().as_mut_unchecked() };
remove_mmu_write_entry(addr, region, inner.mmu_write.as_mut(), &mut inner.vmem);
remove_mmu_write_entry(addr, region, inner.mmu_write_tcm.as_mut(), &mut inner.vmem_tcm);
}
}

Expand Down Expand Up @@ -455,9 +456,7 @@ impl Mmu for MmuArm7 {
}

fn remove_write(&self, addr: u32, region: &MemRegion) {
unsafe {
let mmu = (*self.inner.get()).mmu_write.as_mut();
remove_mmu_entry(addr, region, mmu);
}
let inner = unsafe { self.inner.get().as_mut_unchecked() };
remove_mmu_write_entry(addr, region, inner.mmu_write.as_mut(), &mut inner.vmem);
}
}
2 changes: 1 addition & 1 deletion src/jit/assembler/block_reg_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::utils::HeapMem;
use crate::IS_DEBUG;
use std::intrinsics::unlikely;

const DEBUG: bool = IS_DEBUG;
const DEBUG: bool = false;

pub const ALLOCATION_REGS: RegReserve = reg_reserve!(Reg::R4, Reg::R5, Reg::R6, Reg::R7, Reg::R8, Reg::R9, Reg::R10, Reg::R11);
const SCRATCH_REGS: RegReserve = reg_reserve!(Reg::R0, Reg::R1, Reg::R2, Reg::R3, Reg::R12, Reg::LR);
Expand Down
93 changes: 43 additions & 50 deletions src/jit/emitter/emit_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,77 +84,71 @@ impl<const CPU: CpuType> JitAsm<'_, CPU> {
block_asm.mov(op1, post_addr_reg);
}

self.emit_write(op0, value_reg, addr_reg, block_asm, op.mem_transfer_single_signed(), amount, thumb, false);
self.emit_write(op0, value_reg, addr_reg, block_asm, amount, thumb, false);

block_asm.free_reg(value_reg);
block_asm.free_reg(addr_reg);
block_asm.free_reg(post_addr_reg);
}

fn emit_write(&mut self, op0: Reg, value_reg: BlockReg, addr_reg: BlockReg, block_asm: &mut BlockAsm, signed: bool, amount: MemoryAmount, thumb: bool, is_swp: bool) {
fn emit_write(&mut self, op0: Reg, value_reg: BlockReg, addr_reg: BlockReg, block_asm: &mut BlockAsm, amount: MemoryAmount, thumb: bool, is_swp: bool) {
let fast_write_value_reg = block_asm.new_reg();
let fast_write_next_addr_reg = block_asm.new_reg();
let fast_write_addr_masked_reg = block_asm.new_reg();

let slow_write_patch_label = block_asm.new_label();
let slow_write_label = block_asm.new_label();
let continue_label = block_asm.new_label();

let cpsr_backup_reg = block_asm.new_reg();
block_asm.mrs_cpsr(cpsr_backup_reg);

let mmu_ptr = get_mmu!(self.emu, CPU).get_mmu_write_tcm().as_ptr();
if !thumb && op0 == Reg::PC {
// When op0 is PC, it's read as PC+12
// Don't need to restore it, since breakouts only happen when PC was written to
block_asm.add(value_reg, value_reg, 4);
}

let fast_write_addr_reg = block_asm.new_reg();
let fast_mmu_ptr_reg = block_asm.new_reg();
let fast_mmu_index_reg = block_asm.new_reg();
let fast_mmu_offset_reg = block_asm.new_reg();
block_asm.branch(slow_write_label, Cond::NV);
block_asm.pad_block(slow_write_label, -3);

let mmu = get_mmu!(self.emu, CPU);
let base_ptr = mmu.get_base_tcm_ptr();
let size = if amount == MemoryAmount::Double { MemoryAmount::Word.size() } else { amount.size() };
block_asm.bic(fast_write_addr_reg, addr_reg, 0xF0000000 | (size as u32 - 1));
block_asm.mov(fast_mmu_index_reg, (fast_write_addr_reg.into(), ShiftType::Lsr, BlockOperand::from(mmu::MMU_PAGE_SHIFT as u32)));
block_asm.mov(fast_mmu_ptr_reg, mmu_ptr as u32);
block_asm.transfer_read(
fast_mmu_offset_reg,
fast_mmu_ptr_reg,
(fast_mmu_index_reg.into(), ShiftType::Lsl, BlockOperand::from(2)),
false,
MemoryAmount::Word,
);

block_asm.cmp(fast_mmu_offset_reg, 0);
block_asm.branch(slow_write_label, Cond::EQ);

let shm_ptr = get_mem!(self.emu).shm.as_ptr();

block_asm.bfc(fast_write_addr_reg, mmu::MMU_PAGE_SHIFT as u8, 32 - mmu::MMU_PAGE_SHIFT as u8);
block_asm.add(fast_write_addr_reg, fast_mmu_offset_reg, fast_write_addr_reg);
block_asm.mov(fast_mmu_ptr_reg, shm_ptr as u32);
block_asm.bic(fast_write_addr_masked_reg, addr_reg, 0xF0000000 | (size as u32 - 1));
block_asm.transfer_write(
value_reg,
fast_mmu_ptr_reg,
fast_write_addr_reg,
signed,
fast_write_addr_masked_reg,
base_ptr as u32,
false,
if amount == MemoryAmount::Double { MemoryAmount::Word } else { amount },
);
if amount == MemoryAmount::Double {
block_asm.add(fast_write_addr_reg, fast_write_addr_reg, 4);
block_asm.transfer_write(Reg::from(op0 as u8 + 1), fast_mmu_ptr_reg, fast_write_addr_reg, signed, MemoryAmount::Word);
let op0 = Reg::from(op0 as u8 + 1);
block_asm.add(fast_write_next_addr_reg, addr_reg, 4);
block_asm.bic(fast_write_addr_masked_reg, fast_write_next_addr_reg, 0xF0000000 | (size as u32 - 1));
block_asm.transfer_write(op0, fast_write_addr_masked_reg, base_ptr as u32, false, MemoryAmount::Word);
}

block_asm.msr_cpsr(cpsr_backup_reg);
block_asm.branch_fallthrough(continue_label, Cond::AL);
block_asm.branch(slow_write_patch_label, Cond::AL);

block_asm.branch(continue_label, Cond::AL);
block_asm.label_unlikely(slow_write_patch_label);
let cpsr_backup_reg = block_asm.new_reg();
block_asm.mrs_cpsr(cpsr_backup_reg);
if IS_DEBUG {
block_asm.call1(inst_slow_mem_patch as *const (), self.jit_buf.current_pc);
} else {
block_asm.call(inst_slow_mem_patch as *const ());
}
block_asm.msr_cpsr(cpsr_backup_reg);
block_asm.branch(slow_write_label, Cond::AL);

block_asm.label_unlikely(slow_write_label);
block_asm.msr_cpsr(cpsr_backup_reg);
block_asm.save_context();

if !thumb && op0 == Reg::PC {
// When op0 is PC, it's read as PC+12
// Don't need to restore it, since breakouts only happen when PC was written to
block_asm.add(value_reg, value_reg, 4);
}
block_asm.save_context();

let func_addr = if is_swp {
Self::get_inst_mem_handler_func::<true, true>(signed, amount)
Self::get_inst_mem_handler_func::<true, true>(false, amount)
} else {
Self::get_inst_mem_handler_func::<true, false>(signed, amount)
Self::get_inst_mem_handler_func::<true, false>(false, amount)
};
block_asm.call4(
func_addr,
Expand All @@ -168,11 +162,10 @@ impl<const CPU: CpuType> JitAsm<'_, CPU> {
block_asm.branch(continue_label, Cond::AL);
block_asm.label(continue_label);

block_asm.free_reg(fast_mmu_offset_reg);
block_asm.free_reg(fast_mmu_index_reg);
block_asm.free_reg(fast_mmu_ptr_reg);
block_asm.free_reg(fast_write_addr_reg);
block_asm.free_reg(cpsr_backup_reg);
block_asm.free_reg(fast_write_addr_masked_reg);
block_asm.free_reg(fast_write_next_addr_reg);
block_asm.free_reg(fast_write_value_reg);
}

fn emit_single_transfer_read(&mut self, block_asm: &mut BlockAsm, pre: bool, write_back: bool, amount: MemoryAmount, thumb: bool) {
Expand Down Expand Up @@ -771,7 +764,7 @@ impl<const CPU: CpuType> JitAsm<'_, CPU> {
self.emit_read(op0, addr_reg, block_asm, false, amount, false, true);
block_asm.mov(read_reg, op0);
block_asm.mov(op1, value_reg);
self.emit_write(op1, value_reg, addr_reg, block_asm, false, amount, false, true);
self.emit_write(op1, value_reg, addr_reg, block_asm, amount, false, true);
block_asm.mov(op0, read_reg);

block_asm.free_reg(addr_reg);
Expand Down
27 changes: 3 additions & 24 deletions src/jit/jit_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use crate::utils::{HeapMem, HeapMemU8};
use paste::paste;
use std::collections::VecDeque;
use std::intrinsics::unlikely;
use std::marker::ConstParamTy;
use std::ops::Deref;
use std::{ptr, slice};
use CpuType::{ARM7, ARM9};
Expand All @@ -23,14 +22,6 @@ const JIT_MEMORY_SIZE: usize = 24 * 1024 * 1024;
pub const JIT_LIVE_RANGE_PAGE_SIZE_SHIFT: u32 = 10;
const JIT_LIVE_RANGE_PAGE_SIZE: u32 = 1 << JIT_LIVE_RANGE_PAGE_SIZE_SHIFT;

#[derive(ConstParamTy, Eq, PartialEq)]
pub enum JitRegion {
Itcm,
Main,
Wram,
VramArm7,
}

#[derive(Copy, Clone)]
pub struct JitEntry(pub *const extern "C" fn());

Expand Down Expand Up @@ -329,7 +320,7 @@ impl JitMemory {
}

#[inline(never)]
pub fn invalidate_block<const REGION: JitRegion>(&mut self, guest_addr: u32, size: usize) {
pub fn invalidate_block(&mut self, guest_addr: u32, size: usize) {
macro_rules! invalidate {
($guest_addr:expr) => {{
let live_range = unsafe { self.jit_memory_map.get_live_range($guest_addr).as_mut_unchecked() };
Expand All @@ -345,20 +336,8 @@ impl JitMemory {
}};
}

match REGION {
JitRegion::Itcm => {
invalidate!(guest_addr);
invalidate!(guest_addr + size as u32 - 1);
}
JitRegion::Main => {
invalidate!(guest_addr);
invalidate!(guest_addr + size as u32 - 1);
}
JitRegion::Wram | JitRegion::VramArm7 => {
invalidate!(guest_addr);
invalidate!(guest_addr + size as u32 - 1);
}
}
invalidate!(guest_addr);
invalidate!(guest_addr + size as u32 - 1);
}

pub fn invalidate_wram(&mut self) {
Expand Down
5 changes: 3 additions & 2 deletions src/mmap/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,9 @@ impl VirtualMem {
}

pub fn set_region_protection(&mut self, start: usize, size: usize, mem_region: &MemRegion, read: bool, write: bool, exe: bool) {
let start = mem_region.start + start & (mem_region.size - 1);
for addr_offset in (start..mem_region.end).step_by(mem_region.size) {
let base_offset = start - mem_region.start;
let base_offset = base_offset & (mem_region.size - 1);
for addr_offset in (mem_region.start + base_offset..mem_region.end).step_by(mem_region.size) {
unsafe { set_protection(self.ptr.add(addr_offset), size, read, write, exe) }
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/mmap/vita.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,9 @@ impl VirtualMem {
}

pub fn set_region_protection(&mut self, start: usize, size: usize, mem_region: &MemRegion, read: bool, write: bool, exe: bool) {
let start = mem_region.start + start & (mem_region.size - 1);
for addr_offset in (start..mem_region.end).step_by(mem_region.size) {
let base_offset = start - mem_region.start;
let base_offset = base_offset & (mem_region.size - 1);
for addr_offset in (mem_region.start + base_offset..mem_region.end).step_by(mem_region.size) {
unsafe { set_protection(self.ptr.add(addr_offset), size, read, write, exe) }
}
}
Expand Down

0 comments on commit f578dd4

Please sign in to comment.