Skip to content

Commit

Permalink
jit: Use naked function to store host sp
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak committed Jan 12, 2025
1 parent f29613e commit 115f222
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 34 deletions.
10 changes: 0 additions & 10 deletions src/jit/assembler/block_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,6 @@ impl BlockAsm {

instance.insert_inst(Generic::Prologue);

// First argument is store_host_sp: bool
if !is_common_fun {
instance.cmp(BlockReg::Fixed(Reg::R0), 0);
instance.start_cond_block(Cond::NE);
let host_sp_addr_reg = thread_regs_addr_reg;
instance.mov(host_sp_addr_reg, host_sp_ptr as u32);
instance.store_u32(BlockReg::Fixed(Reg::SP), host_sp_addr_reg, 0);
instance.end_cond_block();
}

instance.sub(BlockReg::Fixed(Reg::SP), BlockReg::Fixed(Reg::SP), ANY_REG_LIMIT as u32 * 4); // Reserve for spilled registers

if !is_common_fun {
Expand Down
12 changes: 6 additions & 6 deletions src/jit/inst_branch_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ fn check_scheduler<const CPU: CpuType>(asm: &mut JitAsm<CPU>, current_pc: u32) {
}
}

pub unsafe extern "C" fn call_jit_fun<const CPU: CpuType>(asm: &mut JitAsm<CPU>, target_pc: u32, store_host_sp: bool) {
pub unsafe extern "C" fn call_jit_fun<const CPU: CpuType>(asm: &mut JitAsm<CPU>, target_pc: u32) {
get_regs_mut!(asm.emu, CPU).set_thumb(target_pc & 1 == 1);

let jit_entry = get_jit!(asm.emu).get_jit_start_addr(align_guest_pc(target_pc));
let jit_entry: extern "C" fn(bool) = mem::transmute(jit_entry);
jit_entry(store_host_sp);
let jit_entry: extern "C" fn() = mem::transmute(jit_entry);
jit_entry();
}

fn pre_branch<const CPU: CpuType, const HAS_LR_RETURN: bool>(asm: &mut JitAsm<CPU>, total_cycles: u16, lr: u32, current_pc: u32) {
Expand Down Expand Up @@ -120,7 +120,7 @@ pub unsafe extern "C" fn branch_reg<const CPU: CpuType, const HAS_LR_RETURN: boo
if CPU == ARM9 {
asm.runtime_data.increment_stack_depth();
}
call_jit_fun(asm, target_pc, false);
call_jit_fun(asm, target_pc);
if CPU == ARM9 {
asm.runtime_data.decrement_stack_depth();
}
Expand All @@ -139,8 +139,8 @@ pub unsafe extern "C" fn branch_imm<const CPU: CpuType, const THUMB: bool, const
}
get_regs_mut!(asm.emu, CPU).set_thumb(THUMB);
let entry = (*target_entry).0;
let entry: extern "C" fn(bool) = mem::transmute(entry);
entry(false);
let entry: extern "C" fn() = mem::transmute(entry);
entry();
if CPU == ARM9 {
asm.runtime_data.decrement_stack_depth();
}
Expand Down
37 changes: 23 additions & 14 deletions src/jit/jit_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::jit::reg::Reg;
use crate::jit::reg::{reg_reserve, RegReserve};
use crate::logging::debug_println;
use crate::{get_jit_asm_ptr, CURRENT_RUNNING_CPU, DEBUG_LOG, IS_DEBUG};
use std::arch::naked_asm;
use std::cell::UnsafeCell;
use std::intrinsics::unlikely;
use std::{mem, ptr};
Expand Down Expand Up @@ -167,7 +168,7 @@ pub fn align_guest_pc(guest_pc: u32) -> u32 {
guest_pc & guest_pc_mask
}

pub extern "C" fn hle_bios_uninterrupt<const CPU: CpuType>(store_host_sp: bool) {
pub extern "C" fn hle_bios_uninterrupt<const CPU: CpuType>() {
let asm = unsafe { get_jit_asm_ptr::<CPU>().as_mut_unchecked() };
if IS_DEBUG {
asm.runtime_data.set_branch_out_pc(get_regs!(asm.emu, CPU).pc);
Expand All @@ -176,34 +177,32 @@ pub extern "C" fn hle_bios_uninterrupt<const CPU: CpuType>(store_host_sp: bool)
asm.runtime_data.accumulated_cycles += 3;
bios::uninterrupt::<CPU>(asm.emu);
if unlikely(get_cpu_regs!(asm.emu, CPU).is_halted()) {
if !store_host_sp {
unsafe { exit_guest_context!(asm) };
}
unsafe { exit_guest_context!(asm) };
} else {
unsafe { call_jit_fun(asm, get_regs_mut!(asm.emu, CPU).pc, store_host_sp) };
unsafe { call_jit_fun(asm, get_regs_mut!(asm.emu, CPU).pc) };
}
}

pub extern "C" fn emit_code_block(store_host_sp: bool) {
pub extern "C" fn emit_code_block() {
match unsafe { CURRENT_RUNNING_CPU } {
ARM9 => {
let asm = unsafe { get_jit_asm_ptr::<{ ARM9 }>().as_mut_unchecked() };
let guest_pc = get_regs!(asm.emu, ARM9).pc;
let aligned_guest_pc = align_guest_pc(guest_pc);
let thumb = (guest_pc & 1) == 1;
emit_code_block_internal::<{ ARM9 }>(asm, store_host_sp, aligned_guest_pc, thumb)
emit_code_block_internal::<{ ARM9 }>(asm, aligned_guest_pc, thumb)
}
ARM7 => {
let asm = unsafe { get_jit_asm_ptr::<{ ARM7 }>().as_mut_unchecked() };
let guest_pc = get_regs!(asm.emu, ARM7).pc;
let aligned_guest_pc = align_guest_pc(guest_pc);
let thumb = (guest_pc & 1) == 1;
emit_code_block_internal::<{ ARM7 }>(asm, store_host_sp, aligned_guest_pc, thumb)
emit_code_block_internal::<{ ARM7 }>(asm, aligned_guest_pc, thumb)
}
}
}

fn emit_code_block_internal<const CPU: CpuType>(asm: &mut JitAsm<CPU>, store_host_sp: bool, guest_pc: u32, thumb: bool) {
fn emit_code_block_internal<const CPU: CpuType>(asm: &mut JitAsm<CPU>, guest_pc: u32, thumb: bool) {
let mut uncond_branch_count = 0;
let mut pc_offset = 0;
let get_inst_info = if thumb {
Expand Down Expand Up @@ -296,7 +295,7 @@ fn emit_code_block_internal<const CPU: CpuType>(asm: &mut JitAsm<CPU>, store_hos
todo!()
}
let (insert_entry, flushed) = get_jit_mut!(asm.emu).insert_block(opcodes, guest_pc, CPU, asm.emu);
let jit_entry: extern "C" fn(bool) = unsafe { mem::transmute(insert_entry) };
let jit_entry: extern "C" fn() = unsafe { mem::transmute(insert_entry) };

if DEBUG_LOG {
// println!("{CPU:?} Mapping {guest_pc:#010x} to {:#010x}", jit_entry as *const fn() as usize);
Expand All @@ -305,12 +304,23 @@ fn emit_code_block_internal<const CPU: CpuType>(asm: &mut JitAsm<CPU>, store_hos
(jit_entry, flushed)
};

jit_entry(store_host_sp);
if flushed && !store_host_sp {
jit_entry();
if flushed {
unsafe { exit_guest_context!(asm) };
}
}

#[naked]
unsafe extern "C" fn call_jit_entry(entry: *const fn(), host_sp_ptr: *mut usize) {
#[rustfmt::skip]
naked_asm!(
"push {{r4-r12,lr}}",
"str sp, [r1]",
"blx r0",
"pop {{r4-r12,pc}}",
);
}

fn execute_internal<const CPU: CpuType>(guest_pc: u32) -> u16 {
let asm = unsafe { get_jit_asm_ptr::<CPU>().as_mut_unchecked() };

Expand All @@ -321,7 +331,6 @@ fn execute_internal<const CPU: CpuType>(guest_pc: u32) -> u16 {
get_regs_mut!(asm.emu, CPU).set_thumb(thumb);

let jit_entry = get_jit!(asm.emu).get_jit_start_addr(align_guest_pc(guest_pc));
let jit_entry: extern "C" fn(bool) = unsafe { mem::transmute(jit_entry) };

debug_println!("{CPU:?} Enter jit addr {:x}", jit_entry as usize);

Expand All @@ -335,7 +344,7 @@ fn execute_internal<const CPU: CpuType>(guest_pc: u32) -> u16 {
jit_entry
};

jit_entry(true);
unsafe { call_jit_entry(jit_entry as _, ptr::addr_of_mut!(asm.runtime_data.host_sp)) };

if IS_DEBUG {
assert_ne!(
Expand Down
8 changes: 4 additions & 4 deletions src/jit/jit_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub enum JitRegion {
}

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

unsafe impl Sync for JitEntry {}

Expand Down Expand Up @@ -256,7 +256,7 @@ impl JitMemory {
(allocated_offset_addr, aligned_size, flushed)
}

pub fn insert_block(&mut self, opcodes: &[u32], guest_pc: u32, cpu_type: CpuType, emu: &Emu) -> (*const extern "C" fn(bool), bool) {
pub fn insert_block(&mut self, opcodes: &[u32], guest_pc: u32, cpu_type: CpuType, emu: &Emu) -> (*const extern "C" fn(), bool) {
macro_rules! insert {
($entries:expr, $live_ranges:expr, $region:expr, [$($cpu_entry:expr),+]) => {{
let ret = insert!($entries, $live_ranges);
Expand All @@ -270,7 +270,7 @@ impl JitMemory {
($entries:expr, $live_ranges:expr) => {{
let (allocated_offset_addr, aligned_size, flushed) = self.insert(opcodes);

let jit_entry_addr = (allocated_offset_addr + self.mem.as_ptr() as usize) as *const extern "C" fn(bool);
let jit_entry_addr = (allocated_offset_addr + self.mem.as_ptr() as usize) as *const extern "C" fn();

let entries_index = (guest_pc >> 1) as usize;
let entries_index = entries_index % $entries.len();
Expand Down Expand Up @@ -324,7 +324,7 @@ impl JitMemory {
}
}

pub fn get_jit_start_addr(&self, guest_pc: u32) -> *const extern "C" fn(bool) {
pub fn get_jit_start_addr(&self, guest_pc: u32) -> *const extern "C" fn() {
unsafe { (*self.jit_memory_map.get_jit_entry(guest_pc)).0 }
}

Expand Down

0 comments on commit 115f222

Please sign in to comment.