Skip to content

Commit

Permalink
Implement str writeback for equal base and dest register
Browse files Browse the repository at this point in the history
* Map vram addresses for arm9
  • Loading branch information
Grarak committed Jan 11, 2025
1 parent 5b389ad commit f81b1e7
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 76 deletions.
31 changes: 11 additions & 20 deletions src/jit/emitter/emit_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,21 @@ impl<const CPU: CpuType> JitAsm<'_, CPU> {
reg
};

let value_reg = block_asm.new_reg();
block_asm.mov(value_reg, op0);

if write_back {
block_asm.mov(op1, post_addr_reg);
}

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

if !thumb && op0 == Reg::PC && write_back && op1 == Reg::PC {
todo!()
}
self.emit_write(op0, value_reg, addr_reg, block_asm, op.mem_transfer_single_signed(), 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, 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, signed: bool, amount: MemoryAmount, thumb: bool, is_swp: bool) {
let slow_write_label = block_asm.new_label();
let continue_label = block_asm.new_label();

Expand Down Expand Up @@ -126,7 +126,7 @@ impl<const CPU: CpuType> JitAsm<'_, CPU> {
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.transfer_write(
op0,
value_reg,
fast_mmu_ptr_reg,
fast_write_addr_reg,
signed,
Expand All @@ -145,18 +145,10 @@ impl<const CPU: CpuType> JitAsm<'_, CPU> {
block_asm.msr_cpsr(cpsr_backup_reg);
block_asm.save_context();

let op0_addr = get_regs!(self.emu, CPU).get_reg(op0) as *const _ as u32;
let op0_addr_reg = block_asm.new_reg();
block_asm.mov(op0_addr_reg, op0_addr);

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
let tmp_pc_reg = block_asm.new_reg();
block_asm.mov(tmp_pc_reg, self.jit_buf.current_pc + 12);
block_asm.store_u32(tmp_pc_reg, op0_addr_reg, 0);

block_asm.free_reg(tmp_pc_reg);
block_asm.add(value_reg, value_reg, 4);
}

let func_addr = if is_swp {
Expand All @@ -167,9 +159,9 @@ impl<const CPU: CpuType> JitAsm<'_, CPU> {
block_asm.call4(
func_addr,
addr_reg,
op0_addr_reg,
value_reg,
self.jit_buf.current_pc | (thumb as u32),
self.jit_buf.insts_cycle_counts[self.jit_buf.current_index] as u32,
(self.jit_buf.insts_cycle_counts[self.jit_buf.current_index] as u32) | ((op0 as u32) << 16),
);
block_asm.restore_reg(Reg::CPSR);

Expand All @@ -181,7 +173,6 @@ impl<const CPU: CpuType> JitAsm<'_, CPU> {
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(op0_addr_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 @@ -769,7 +760,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, addr_reg, block_asm, false, amount, false, true);
self.emit_write(op1, value_reg, addr_reg, block_asm, false, amount, false, true);
block_asm.mov(op0, read_reg);

block_asm.free_reg(addr_reg);
Expand Down
96 changes: 50 additions & 46 deletions src/jit/inst_mem_handler.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::core::emu::get_mem;
use crate::core::CpuType;
use crate::get_jit_asm_ptr;
use crate::jit::reg::Reg;
use crate::jit::MemoryAmount;
use handler::*;
use std::intrinsics::unlikely;

mod handler {
use crate::core::emu::{get_mem_mut, get_regs_mut, Emu};
use crate::core::emu::{get_mem_mut, get_regs, get_regs_mut, Emu};
use crate::core::thread_regs::ThreadRegs;
use crate::core::CpuType;
use crate::jit::reg::{Reg, RegReserve};
Expand All @@ -15,51 +16,50 @@ mod handler {
use std::hint::unreachable_unchecked;
use std::intrinsics::{likely, unlikely};

pub fn handle_request<const CPU: CpuType, const WRITE: bool, const AMOUNT: MemoryAmount, const SIGNED: bool>(op0: &mut u32, addr: u32, emu: &mut Emu) {
if WRITE {
match AMOUNT {
MemoryAmount::Byte => {
emu.mem_write::<CPU, _>(addr, *op0 as u8);
}
MemoryAmount::Half => {
emu.mem_write::<CPU, _>(addr, *op0 as u16);
}
MemoryAmount::Word => {
emu.mem_write::<CPU, _>(addr, *op0);
}
MemoryAmount::Double => {
emu.mem_write::<CPU, _>(addr, *op0);
let next_reg = unsafe { (op0 as *mut u32).offset(1).as_ref().unwrap_unchecked() };
emu.mem_write::<CPU, _>(addr + 4, *next_reg);
}
pub fn handle_request_write<const CPU: CpuType, const AMOUNT: MemoryAmount>(op0: u32, addr: u32, emu: &mut Emu, op0_reg: Reg) {
match AMOUNT {
MemoryAmount::Byte => {
emu.mem_write::<CPU, _>(addr, op0 as u8);
}
} else {
match AMOUNT {
MemoryAmount::Byte => {
if SIGNED {
*op0 = emu.mem_read_with_options::<CPU, true, u8>(addr) as i8 as i32 as u32;
} else {
*op0 = emu.mem_read_with_options::<CPU, true, u8>(addr) as u32;
}
}
MemoryAmount::Half => {
if SIGNED {
*op0 = emu.mem_read_with_options::<CPU, true, u16>(addr) as i16 as i32 as u32;
} else {
*op0 = emu.mem_read_with_options::<CPU, true, u16>(addr) as u32;
}
}
MemoryAmount::Word => {
let value = emu.mem_read_with_options::<CPU, true, u32>(addr);
let shift = (addr & 0x3) << 3;
*op0 = value.wrapping_shl(32 - shift) | (value >> shift)
MemoryAmount::Half => {
emu.mem_write::<CPU, _>(addr, op0 as u16);
}
MemoryAmount::Word => {
emu.mem_write::<CPU, _>(addr, op0);
}
MemoryAmount::Double => {
emu.mem_write::<CPU, _>(addr, op0);
emu.mem_write::<CPU, _>(addr + 4, *get_regs!(emu, CPU).get_reg(Reg::from(op0_reg as u8 + 1)));
}
}
}

pub fn handle_request_read<const CPU: CpuType, const AMOUNT: MemoryAmount, const SIGNED: bool>(op0: &mut u32, addr: u32, emu: &mut Emu) {
match AMOUNT {
MemoryAmount::Byte => {
if SIGNED {
*op0 = emu.mem_read_with_options::<CPU, true, u8>(addr) as i8 as i32 as u32;
} else {
*op0 = emu.mem_read_with_options::<CPU, true, u8>(addr) as u32;
}
MemoryAmount::Double => {
*op0 = emu.mem_read_with_options::<CPU, true, u32>(addr);
let next_reg = unsafe { (op0 as *mut u32).offset(1).as_mut().unwrap_unchecked() };
*next_reg = emu.mem_read_with_options::<CPU, true, u32>(addr + 4);
}
MemoryAmount::Half => {
if SIGNED {
*op0 = emu.mem_read_with_options::<CPU, true, u16>(addr) as i16 as i32 as u32;
} else {
*op0 = emu.mem_read_with_options::<CPU, true, u16>(addr) as u32;
}
}
MemoryAmount::Word => {
let value = emu.mem_read_with_options::<CPU, true, u32>(addr);
let shift = (addr & 0x3) << 3;
*op0 = value.wrapping_shl(32 - shift) | (value >> shift)
}
MemoryAmount::Double => {
*op0 = emu.mem_read_with_options::<CPU, true, u32>(addr);
let next_reg = unsafe { (op0 as *mut u32).offset(1).as_mut().unwrap_unchecked() };
*next_reg = emu.mem_read_with_options::<CPU, true, u32>(addr + 4);
}
}
}

Expand Down Expand Up @@ -156,17 +156,21 @@ pub(super) use imm_breakout;

pub unsafe extern "C" fn inst_mem_handler<const CPU: CpuType, const WRITE: bool, const AMOUNT: MemoryAmount, const SIGNED: bool, const IS_SWP: bool>(
addr: u32,
op0: *mut u32,
op0: u32,
pc: u32,
total_cycles: u16,
total_cycles_reg: u32,
) {
let asm = get_jit_asm_ptr::<CPU>();
handle_request::<CPU, WRITE, AMOUNT, SIGNED>(op0.as_mut().unwrap_unchecked(), addr, (*asm).emu);
if WRITE {
handle_request_write::<CPU, AMOUNT>(op0, addr, (*asm).emu, Reg::from((total_cycles_reg >> 16) as u8));
} else {
handle_request_read::<CPU, AMOUNT, SIGNED>((op0 as *mut u32).as_mut_unchecked(), addr, (*asm).emu);
}
if IS_SWP && unlikely(get_mem!((*asm).emu).breakout_imm) {
todo!()
}
if WRITE && unlikely(get_mem!((*asm).emu).breakout_imm) {
imm_breakout!((*asm), pc, total_cycles);
imm_breakout!((*asm), pc, total_cycles_reg as u16);
}
}

Expand Down
26 changes: 18 additions & 8 deletions src/jit/jit_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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 Down Expand Up @@ -81,7 +82,7 @@ create_jit_blocks!(
[main, regions::MAIN_SIZE],
[shared_wram_arm7, regions::SHARED_WRAM_SIZE],
[wram_arm7, regions::ARM7_WRAM_SIZE],
[vram_arm7, vram::ARM7_SIZE]
[vram, vram::ARM7_SIZE]
);

#[derive(Default)]
Expand All @@ -90,7 +91,7 @@ pub struct JitLiveRanges {
pub main: HeapMemU8<{ (regions::MAIN_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>,
pub shared_wram_arm7: HeapMemU8<{ (regions::SHARED_WRAM_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>,
pub wram_arm7: HeapMemU8<{ (regions::ARM7_WRAM_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>,
pub vram_arm7: HeapMemU8<{ (vram::ARM7_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>,
pub vram: HeapMemU8<{ (vram::ARM7_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>, // Use arm7 vram size for arm9 as well
}

#[cfg(target_os = "linux")]
Expand Down Expand Up @@ -305,6 +306,7 @@ impl JitMemory {
ARM9 => match guest_pc & 0xFF000000 {
regions::ITCM_OFFSET | regions::ITCM_OFFSET2 => insert!(self.jit_entries.itcm, self.jit_live_ranges.itcm, regions::ITCM_REGION, [ARM9]),
regions::MAIN_OFFSET => insert!(self.jit_entries.main, self.jit_live_ranges.main, regions::MAIN_REGION, [ARM9, ARM7]),
regions::VRAM_OFFSET => insert!(self.jit_entries.vram, self.jit_live_ranges.vram),
_ => todo!("{:x}", guest_pc),
},
ARM7 => match guest_pc & 0xFF000000 {
Expand All @@ -316,7 +318,7 @@ impl JitMemory {
insert!(self.jit_entries.shared_wram_arm7, self.jit_live_ranges.shared_wram_arm7, regions::SHARED_WRAM_ARM7_REGION, [ARM7])
}
}
regions::VRAM_OFFSET => insert!(self.jit_entries.vram_arm7, self.jit_live_ranges.vram_arm7),
regions::VRAM_OFFSET => insert!(self.jit_entries.vram, self.jit_live_ranges.vram),
_ => todo!("{:x}", guest_pc),
},
}
Expand Down Expand Up @@ -361,15 +363,23 @@ impl JitMemory {

pub fn invalidate_wram(&mut self) {
if !self.arm7_hle {
self.jit_entries.shared_wram_arm7.fill(DEFAULT_JIT_ENTRY);
self.jit_live_ranges.shared_wram_arm7.fill(0);
for live_range in self.jit_live_ranges.shared_wram_arm7.deref() {
if *live_range != 0 {
self.jit_entries.shared_wram_arm7.fill(DEFAULT_JIT_ENTRY);
self.jit_live_ranges.shared_wram_arm7.fill(0);
return;
}
}
}
}

pub fn invalidate_vram(&mut self) {
if !self.arm7_hle {
self.jit_entries.vram_arm7.fill(DEFAULT_JIT_ENTRY);
self.jit_live_ranges.vram_arm7.fill(0);
for live_range in self.jit_live_ranges.vram.deref() {
if *live_range != 0 {
self.jit_entries.vram.fill(DEFAULT_JIT_ENTRY);
self.jit_live_ranges.vram.fill(0);
return;
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/jit/jit_memory_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl JitMemoryMap {
*map_ptr = get_ptr!(addr, entries.shared_wram_arm7)
}
}
regions::VRAM_OFFSET => *map_ptr = get_ptr!(addr, entries.vram_arm7),
regions::VRAM_OFFSET => *map_ptr = get_ptr!(addr, entries.vram),
_ => {}
}
}
Expand All @@ -73,7 +73,7 @@ impl JitMemoryMap {
*map_ptr = get_ptr!(i, live_ranges.shared_wram_arm7)
}
}
regions::VRAM_OFFSET => *map_ptr = get_ptr!(i, live_ranges.vram_arm7),
regions::VRAM_OFFSET => *map_ptr = get_ptr!(i, live_ranges.vram),
_ => {}
}
}
Expand Down

0 comments on commit f81b1e7

Please sign in to comment.