Skip to content

Commit a81d8f6

Browse files
committed
WIP
1 parent df8098b commit a81d8f6

File tree

8 files changed

+87
-30
lines changed

8 files changed

+87
-30
lines changed

src/jit/inst_branch_handler.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use crate::core::emu::{get_jit, get_regs_mut};
2+
use crate::core::CpuType;
3+
use crate::jit::jit_asm::RETURN_STACK_SIZE;
4+
use crate::jit::jit_asm_common_funs::{exit_guest_context, JitAsmCommonFuns, MAX_LOOP_CYCLE_COUNT};
5+
use crate::{get_jit_asm_ptr, DEBUG_LOG, IS_DEBUG};
6+
use std::intrinsics::unlikely;
7+
use std::mem;
8+
use CpuType::{ARM7, ARM9};
9+
10+
pub unsafe extern "C" fn branch_reg<const CPU: CpuType>(total_cycles: u16, lr: u32, target_pc: u32, current_pc: u32) {
11+
let asm = get_jit_asm_ptr::<CPU>().as_mut_unchecked();
12+
asm.runtime_data.accumulated_cycles += total_cycles + 2 - asm.runtime_data.pre_cycle_count_sum;
13+
let max_count = match CPU {
14+
ARM9 => MAX_LOOP_CYCLE_COUNT * 2,
15+
ARM7 => MAX_LOOP_CYCLE_COUNT,
16+
};
17+
18+
if unlikely(asm.runtime_data.accumulated_cycles >= max_count as u16) {
19+
if IS_DEBUG {
20+
asm.runtime_data.branch_out_pc = current_pc;
21+
}
22+
exit_guest_context!(asm);
23+
} else {
24+
asm.runtime_data.pre_cycle_count_sum = 0;
25+
let return_stack_ptr = asm.runtime_data.return_stack_ptr & (RETURN_STACK_SIZE as u8 - 1);
26+
*asm.runtime_data.return_stack.get_unchecked_mut(return_stack_ptr as usize) = lr;
27+
asm.runtime_data.return_stack_ptr = return_stack_ptr + 1;
28+
29+
if DEBUG_LOG {
30+
JitAsmCommonFuns::<CPU>::debug_push_return_stack(current_pc, lr, return_stack_ptr);
31+
JitAsmCommonFuns::<CPU>::debug_branch_reg(current_pc, target_pc);
32+
}
33+
34+
let thumb = target_pc & 1 != 0;
35+
get_regs_mut!(asm.emu, CPU).set_thumb(thumb);
36+
let aligned_pc_mask = !(1 | ((!thumb as u32) << 1));
37+
let aligned_pc = target_pc & aligned_pc_mask;
38+
39+
let jit_entry = get_jit!(asm.emu).get_jit_start_addr::<CPU>(aligned_pc);
40+
let jit_entry: extern "C" fn(bool) = unsafe { mem::transmute(jit_entry) };
41+
jit_entry(false);
42+
43+
asm.runtime_data.pre_cycle_count_sum = total_cycles;
44+
}
45+
}

src/jit/inst_mem_handler.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod handler {
1313
use crate::jit::reg::{Reg, RegReserve};
1414
use crate::jit::MemoryAmount;
1515
use crate::logging::debug_println;
16+
use std::hint::unreachable_unchecked;
1617
use std::intrinsics::{likely, unlikely};
1718

1819
pub fn handle_request<const CPU: CpuType, const WRITE: bool, const AMOUNT: MemoryAmount, const SIGNED: bool>(op0: &mut u32, addr: u32, emu: &mut Emu) {
@@ -81,7 +82,7 @@ mod handler {
8182
*get_regs_mut!(emu, CPU).get_reg_mut(op0) += 0x40;
8283
}
8384
if CPU == CpuType::ARM7 {
84-
todo!()
85+
unsafe { unreachable_unchecked() }
8586
}
8687
return;
8788
}
@@ -135,7 +136,7 @@ mod handler {
135136
}
136137

137138
if USER && unlikely(rlist.is_reserved(Reg::PC)) {
138-
todo!("restore spsr")
139+
unsafe { unreachable_unchecked() }
139140
}
140141
}
141142

@@ -159,13 +160,7 @@ macro_rules! imm_breakout {
159160
$asm.runtime_data.accumulated_cycles += $total_cycles - $asm.runtime_data.pre_cycle_count_sum;
160161
crate::core::emu::get_regs_mut!($asm.emu, CPU).pc = $pc + if $thumb { 3 } else { 4 };
161162
crate::core::emu::get_mem_mut!($asm.emu).breakout_imm = false;
162-
// r4-r12,pc since we need an even amount of registers for 8 byte alignment, in case the compiler decides to use neon instructions
163-
std::arch::asm!(
164-
"mov sp, {}",
165-
"pop {{r4-r12,pc}}",
166-
in(reg) $asm.runtime_data.host_sp
167-
);
168-
std::hint::unreachable_unchecked();
163+
crate::jit::jit_asm_common_funs::exit_guest_context!($asm);
169164
}};
170165
}
171166
pub(super) use imm_breakout;

src/jit/jit_asm.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ use crate::jit::assembler::BlockAsmBuf;
77
use crate::jit::disassembler::lookup_table::lookup_opcode;
88
use crate::jit::disassembler::thumb::lookup_table_thumb::lookup_thumb_opcode;
99
use crate::jit::inst_info::InstInfo;
10-
use crate::jit::jit_asm_common_funs::JitAsmCommonFuns;
10+
use crate::jit::jit_asm_common_funs::{exit_guest_context, JitAsmCommonFuns};
1111
use crate::jit::op::Op;
1212
use crate::jit::reg::Reg;
1313
use crate::jit::reg::{reg_reserve, RegReserve};
1414
use crate::logging::debug_println;
1515
use crate::{get_jit_asm_ptr, DEBUG_LOG, IS_DEBUG};
16-
use std::arch::asm;
1716
use std::cell::UnsafeCell;
18-
use std::hint::unreachable_unchecked;
1917
use std::intrinsics::unlikely;
2018
use std::{mem, ptr};
2119

@@ -117,15 +115,7 @@ pub extern "C" fn hle_bios_uninterrupt<const CPU: CpuType>(store_host_sp: bool)
117115
bios::uninterrupt::<CPU>(asm.emu);
118116
if unlikely(get_cpu_regs!(asm.emu, CPU).is_halted()) {
119117
if !store_host_sp {
120-
// r4-r12,pc since we need an even amount of registers for 8 byte alignment, in case the compiler decides to use neon instructions
121-
unsafe {
122-
asm!(
123-
"mov sp, {}",
124-
"pop {{r4-r12,pc}}",
125-
in(reg) asm.runtime_data.host_sp
126-
);
127-
unreachable_unchecked();
128-
}
118+
unsafe { exit_guest_context!(asm) };
129119
}
130120
} else {
131121
let jit_entry = get_jit!(asm.emu).get_jit_start_addr::<CPU>(get_regs!(asm.emu, CPU).pc);

src/jit/jit_asm_common_funs.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@ use crate::jit::{jit_memory_map, Cond, ShiftType};
99
use crate::{DEBUG_LOG, IS_DEBUG};
1010
use std::ptr;
1111

12+
pub const MAX_LOOP_CYCLE_COUNT: u32 = 255;
13+
14+
macro_rules! exit_guest_context {
15+
($asm:expr) => {{
16+
// r4-r12,pc since we need an even amount of registers for 8 byte alignment, in case the compiler decides to use neon instructions
17+
std::arch::asm!(
18+
"mov sp, {}",
19+
"pop {{r4-r12,pc}}",
20+
in(reg) $asm.runtime_data.host_sp
21+
);
22+
std::hint::unreachable_unchecked();
23+
}};
24+
}
25+
26+
use crate::jit::inst_branch_handler::branch_reg;
27+
pub(crate) use exit_guest_context;
28+
1229
pub struct JitAsmCommonFuns<const CPU: CpuType> {
1330
branch_return_stack: usize,
1431
branch_reg: usize,
@@ -34,7 +51,8 @@ impl<const CPU: CpuType> JitAsmCommonFuns<CPU> {
3451
};
3552
JitAsmCommonFuns {
3653
branch_return_stack: create_function(Self::emit_branch_return_stack, &format!("{CPU:?}_branch_return_stack")),
37-
branch_reg: create_function(Self::emit_branch_reg, &format!("{CPU:?}_branch_reg")),
54+
// branch_reg: create_function(Self::emit_branch_reg, &format!("{CPU:?}_branch_reg")),
55+
branch_reg: 0,
3856
}
3957
}
4058

@@ -131,7 +149,6 @@ impl<const CPU: CpuType> JitAsmCommonFuns<CPU> {
131149
let result_accumulated_cycles_reg = block_asm.new_reg();
132150
Self::emit_count_cycles(block_asm, total_cycles_reg, runtime_data_addr_reg, result_accumulated_cycles_reg);
133151

134-
const MAX_LOOP_CYCLE_COUNT: u32 = 255;
135152
block_asm.cmp(
136153
result_accumulated_cycles_reg,
137154
match CPU {
@@ -336,17 +353,19 @@ impl<const CPU: CpuType> JitAsmCommonFuns<CPU> {
336353

337354
pub fn emit_call_branch_reg(&self, block_asm: &mut BlockAsm, total_cycles: u16, lr_reg: BlockReg, target_pc_reg: BlockReg, current_pc: u32) {
338355
if IS_DEBUG {
339-
block_asm.call4_common(self.branch_reg, total_cycles as u32, lr_reg, target_pc_reg, current_pc);
356+
// block_asm.call4_common(self.branch_reg, total_cycles as u32, lr_reg, target_pc_reg, current_pc);
357+
block_asm.call4(branch_reg::<CPU> as *const (), total_cycles as u32, lr_reg, target_pc_reg, current_pc);
340358
} else {
341-
block_asm.call3_common(self.branch_reg, total_cycles as u32, lr_reg, target_pc_reg);
359+
// block_asm.call3_common(self.branch_reg, total_cycles as u32, lr_reg, target_pc_reg);
360+
block_asm.call3(branch_reg::<CPU> as *const (), total_cycles as u32, lr_reg, target_pc_reg);
342361
}
343362
}
344363

345-
extern "C" fn debug_push_return_stack(current_pc: u32, lr_pc: u32, stack_size: u8) {
364+
pub extern "C" fn debug_push_return_stack(current_pc: u32, lr_pc: u32, stack_size: u8) {
346365
println!("{CPU:?} push {lr_pc:x} to return stack with size {stack_size} at {current_pc:x}")
347366
}
348367

349-
extern "C" fn debug_branch_reg(current_pc: u32, target_pc: u32) {
368+
pub extern "C" fn debug_branch_reg(current_pc: u32, target_pc: u32) {
350369
println!("{CPU:?} branch reg from {current_pc:x} to {target_pc:x}")
351370
}
352371

src/jit/jit_memory.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ impl JitMemory {
313313
unsafe { (*self.jit_memory_map.get_jit_entry::<CPU>(guest_pc)).0 }
314314
}
315315

316+
#[inline(never)]
316317
pub fn invalidate_block<const REGION: JitRegion>(&mut self, guest_addr: u32, size: usize) {
317318
macro_rules! invalidate {
318319
($guest_addr:expr, $cpu:expr, [$($cpu_entry:expr),+]) => {{

src/jit/jit_memory_map.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl JitMemoryMap {
114114
let addr = (addr & 0x0FFFFFFF) >> 1;
115115
macro_rules! get_jit_entry {
116116
($map:expr) => {{
117-
unsafe { ($map[(addr >> BLOCK_SHIFT) as usize] as *mut JitEntry).add((addr as usize) & (BLOCK_SIZE - 1)) }
117+
unsafe { ((*$map.get_unchecked((addr >> BLOCK_SHIFT) as usize)) as *mut JitEntry).add((addr as usize) & (BLOCK_SIZE - 1)) }
118118
}};
119119
}
120120
match CPU {
@@ -124,9 +124,14 @@ impl JitMemoryMap {
124124
}
125125

126126
pub fn get_live_range<const CPU: CpuType>(&self, addr: u32) -> *mut u8 {
127+
macro_rules! get_live_range {
128+
($map:expr) => {{
129+
unsafe { (*$map.get_unchecked((addr >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 3)) as usize)) as _ }
130+
}};
131+
}
127132
match CPU {
128-
ARM9 => self.live_ranges_map_arm9[(addr >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 3)) as usize] as _,
129-
ARM7 => self.live_ranges_map_arm7[(addr >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 3)) as usize] as _,
133+
ARM9 => get_live_range!(self.live_ranges_map_arm9),
134+
ARM7 => get_live_range!(self.live_ranges_map_arm7),
130135
}
131136
}
132137

src/jit/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::{mem, ops};
55
pub mod assembler;
66
pub mod disassembler;
77
mod emitter;
8+
mod inst_branch_handler;
89
mod inst_cp15_handler;
910
mod inst_cpu_regs_handler;
1011
mod inst_exception_handler;

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ pub fn actual_main() {
358358
.name("cpu".to_owned())
359359
.spawn(move || {
360360
set_thread_prio_affinity(ThreadPriority::High, ThreadAffinity::Core2);
361+
println!("Start cpu {:?}", thread::current().id());
361362
run_cpu(
362363
cartridge_io,
363364
fps_clone,

0 commit comments

Comments
 (0)