Skip to content

Commit

Permalink
Dedicated jit memory for arm7
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak committed Feb 1, 2025
1 parent 306aed9 commit bbe372f
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 199 deletions.
2 changes: 1 addition & 1 deletion src/core/emu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ impl Emu {
pub fn new(cartridge_io: CartridgeIo, fps: Arc<AtomicU16>, key_map: Arc<AtomicU32>, touch_points: Arc<AtomicU16>, sound_sampler: Arc<SoundSampler>, settings: Settings) -> Self {
Emu {
common: UnsafeCell::new(Common::new(cartridge_io, fps, key_map)),
mem: UnsafeCell::new(Memory::new(touch_points, sound_sampler)),
mem: UnsafeCell::new(Memory::new(&settings, touch_points, sound_sampler)),
arm7_hle: UnsafeCell::new(Arm7Hle::new()),
settings,
}
Expand Down
5 changes: 3 additions & 2 deletions src/core/memory/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::core::CpuType::ARM9;
use crate::jit::jit_memory::JitMemory;
use crate::logging::debug_println;
use crate::mmap::Shm;
use crate::settings::Settings;
use crate::utils::Convert;
use crate::{utils, DEBUG_LOG};
use std::hint::unreachable_unchecked;
Expand Down Expand Up @@ -744,7 +745,7 @@ impl<const CPU: CpuType, const TCM: bool, T: Convert> MemoryMultipleMemsetIo<CPU
}

impl Memory {
pub fn new(touch_points: Arc<AtomicU16>, sound_sampler: Arc<SoundSampler>) -> Self {
pub fn new(settings: &Settings, touch_points: Arc<AtomicU16>, sound_sampler: Arc<SoundSampler>) -> Self {
Memory {
shm: Shm::new("physical", regions::TOTAL_MEM_SIZE as usize).unwrap(),
wram: Wram::new(),
Expand All @@ -754,7 +755,7 @@ impl Memory {
palettes: Palettes::new(),
vram: Vram::default(),
oam: Oam::new(),
jit: JitMemory::new(),
jit: JitMemory::new(settings),
breakout_imm: false,
mmu_arm9: MmuArm9::new(),
mmu_arm7: MmuArm7::new(),
Expand Down
59 changes: 6 additions & 53 deletions src/jit/assembler/block_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ impl BlockAsm {
self.tmp_regs.func_call_reg
}
};
self.insert_inst(Call::reg(
self.insert_inst(Call::new(
reg,
[
args[0].map(|_| BlockReg::Fixed(Reg::R0)),
Expand All @@ -676,48 +676,6 @@ impl BlockAsm {
));
}

pub fn call_common(&mut self, offset: usize) {
self.call_common_internal(offset, None::<BlockOperand>, None::<BlockOperand>, None::<BlockOperand>, None::<BlockOperand>, true)
}

pub fn call1_common(&mut self, offset: usize, arg0: impl Into<BlockOperand>) {
self.call_common_internal(offset, Some(arg0.into()), None::<BlockOperand>, None::<BlockOperand>, None::<BlockOperand>, true)
}

pub fn call2_common(&mut self, offset: usize, arg0: impl Into<BlockOperand>, arg1: impl Into<BlockOperand>) {
self.call_common_internal(offset, Some(arg0.into()), Some(arg1.into()), None::<BlockOperand>, None::<BlockOperand>, true)
}

pub fn call3_common(&mut self, offset: usize, arg0: impl Into<BlockOperand>, arg1: impl Into<BlockOperand>, arg2: impl Into<BlockOperand>) {
self.call_common_internal(offset, Some(arg0.into()), Some(arg1.into()), Some(arg2.into()), None::<BlockOperand>, true)
}

pub fn call4_common(&mut self, offset: usize, arg0: impl Into<BlockOperand>, arg1: impl Into<BlockOperand>, arg2: impl Into<BlockOperand>, arg3: impl Into<BlockOperand>) {
self.call_common_internal(offset, Some(arg0.into()), Some(arg1.into()), Some(arg2.into()), Some(arg3.into()), true)
}

fn call_common_internal(
&mut self,
offset: usize,
arg0: Option<impl Into<BlockOperand>>,
arg1: Option<impl Into<BlockOperand>>,
arg2: Option<impl Into<BlockOperand>>,
arg3: Option<impl Into<BlockOperand>>,
has_return: bool,
) {
let args = self.handle_call_args(arg0, arg1, arg2, arg3);
self.insert_inst(Call::offset(
offset,
[
args[0].map(|_| BlockReg::Fixed(Reg::R0)),
args[1].map(|_| BlockReg::Fixed(Reg::R1)),
args[2].map(|_| BlockReg::Fixed(Reg::R2)),
args[3].map(|_| BlockReg::Fixed(Reg::R3)),
],
has_return,
));
}

pub fn bkpt(&mut self, id: u16) {
self.insert_inst(Bkpt(id));
}
Expand Down Expand Up @@ -1123,7 +1081,7 @@ impl BlockAsm {
self.buf.opcodes.len()
}

pub fn finalize(&mut self, jit_mem_offset: usize) -> &Vec<u32> {
pub fn finalize(&mut self) -> &Vec<u32> {
// Used to determine what regs to push and pop for prologue and epilogue
let mut used_host_regs = if unlikely(self.is_common_fun) {
self.buf.reg_allocator.dirty_regs & ALLOCATION_REGS
Expand All @@ -1149,15 +1107,10 @@ impl BlockAsm {
continue;
}

let diff = if encoding.is_call_common() {
let opcode_index = (jit_mem_offset >> 2) + index;
let branch_to = u32::from(encoding.index()) >> 2;
branch_to as i32 - opcode_index as i32
} else {
let block_index = u32::from(encoding.index());
let branch_to = self.buf.block_opcode_offsets[block_index as usize];
branch_to as i32 - index as i32
};
let block_index = u32::from(encoding.index());
let branch_to = self.buf.block_opcode_offsets[block_index as usize];
let diff = branch_to as i32 - index as i32;

if diff == 1 && !encoding.has_return() {
self.buf.opcodes[index] = AluShiftImm::mov_al(Reg::R0, Reg::R0);
} else {
Expand Down
75 changes: 17 additions & 58 deletions src/jit/assembler/block_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,19 +187,13 @@ pub struct GenericGuest {
#[bitsize(32)]
#[derive(FromBits)]
pub struct BranchEncoding {
pub index: u26,
pub index: u27,
pub has_return: bool,
pub is_call_common: bool,
pub cond: u4,
}

pub enum CallOp {
Reg(BlockReg),
Offset(usize),
}

pub struct Call {
op: CallOp,
reg: BlockReg,
args: [Option<BlockReg>; 4],
pub has_return: bool,
}
Expand Down Expand Up @@ -1121,29 +1115,15 @@ impl Debug for GenericGuest {
}

impl Call {
pub fn reg(reg: BlockReg, args: [Option<BlockReg>; 4], has_return: bool) -> Self {
Call {
op: CallOp::Reg(reg),
args,
has_return,
}
}

pub fn offset(offset: usize, args: [Option<BlockReg>; 4], has_return: bool) -> Self {
Call {
op: CallOp::Offset(offset),
args,
has_return,
}
pub fn new(reg: BlockReg, args: [Option<BlockReg>; 4], has_return: bool) -> Self {
Call { reg, args, has_return }
}
}

impl BlockInstTrait for Call {
fn get_io(&self) -> (BlockRegSet, BlockRegSet) {
let mut inputs = BlockRegSet::new();
if let CallOp::Reg(reg) = self.op {
inputs += reg;
}
inputs += self.reg;
for &arg in self.args.iter().flatten() {
inputs += arg;
}
Expand All @@ -1162,47 +1142,26 @@ impl BlockInstTrait for Call {
}

fn replace_input_regs(&mut self, old: BlockReg, new: BlockReg) {
if let CallOp::Reg(reg) = &mut self.op {
replace_reg(reg, old, new)
}
replace_reg(&mut self.reg, old, new)
}

fn replace_output_regs(&mut self, _: BlockReg, _: BlockReg) {}

fn emit_opcode(&mut self, alloc: &BlockRegAllocator, opcodes: &mut Vec<u32>, opcode_index: usize, placeholders: &mut BlockAsmPlaceholders) {
match self.op {
CallOp::Reg(reg) => opcodes.push(if self.has_return {
Bx::blx(alloc.for_emit_input(reg), Cond::AL)
} else {
Bx::bx(alloc.for_emit_input(reg), Cond::AL)
}),
CallOp::Offset(offset) => {
// Encode common offset
// Branch offset can only be figured out later
opcodes.push(BranchEncoding::new(u26::new(offset as u32), self.has_return, true, u4::new(Cond::AL as u8)).into());
placeholders.branch.push(opcode_index);
}
}
fn emit_opcode(&mut self, alloc: &BlockRegAllocator, opcodes: &mut Vec<u32>, _: usize, _: &mut BlockAsmPlaceholders) {
opcodes.push(if self.has_return {
Bx::blx(alloc.for_emit_input(self.reg), Cond::AL)
} else {
Bx::bx(alloc.for_emit_input(self.reg), Cond::AL)
});
}
}

impl Debug for Call {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self.op {
CallOp::Reg(reg) => {
if self.has_return {
write!(f, "Blx {reg:?} {:?}", self.args)
} else {
write!(f, "Bx {reg:?} {:?}", self.args)
}
}
CallOp::Offset(offset) => {
if self.has_return {
write!(f, "Bl {offset:x} {:?}", self.args)
} else {
write!(f, "B {offset:x} {:?}", self.args)
}
}
if self.has_return {
write!(f, "Blx {:?} {:?}", self.reg, self.args)
} else {
write!(f, "Bx {:?} {:?}", self.reg, self.args)
}
}
}
Expand Down Expand Up @@ -1235,7 +1194,7 @@ impl BlockInstTrait for Branch {
fn emit_opcode(&mut self, _: &BlockRegAllocator, opcodes: &mut Vec<u32>, opcode_index: usize, placeholders: &mut BlockAsmPlaceholders) {
// Encode label
// Branch offset can only be figured out later
opcodes.push(BranchEncoding::new(u26::new(self.block_index as u32), false, false, u4::new(Cond::AL as u8)).into());
opcodes.push(BranchEncoding::new(u27::new(self.block_index as u32), false, u4::new(Cond::AL as u8)).into());
placeholders.branch.push(opcode_index);
}
}
Expand Down
13 changes: 9 additions & 4 deletions src/jit/jit_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,13 @@ fn emit_code_block_internal<const CPU: CpuType>(asm: &mut JitAsm<CPU>, guest_pc:
let is_unreturnable_branch = !inst_info.out_regs.is_reserved(Reg::LR) && is_uncond_branch;
asm.jit_buf.insts.push(inst_info);

if is_unreturnable_branch || uncond_branch_count == 4 {
if is_unreturnable_branch
|| uncond_branch_count
== match CPU {
ARM9 => 4,
ARM7 => 1,
}
{
break;
}
pc_offset += pc_step;
Expand Down Expand Up @@ -325,9 +331,8 @@ fn emit_code_block_internal<const CPU: CpuType>(asm: &mut JitAsm<CPU>, guest_pc:

block_asm.epilogue();

let opcodes_len = block_asm.emit_opcodes(guest_pc);
let next_jit_entry = get_jit!(asm.emu).get_next_entry(opcodes_len);
let opcodes = block_asm.finalize(next_jit_entry);
block_asm.emit_opcodes(guest_pc);
let opcodes = block_asm.finalize();
if IS_DEBUG && unsafe { BLOCK_LOG } {
for &opcode in opcodes {
println!("0x{opcode:x},");
Expand Down
Loading

0 comments on commit bbe372f

Please sign in to comment.