Skip to content

Commit 6c45d29

Browse files
committed
WIP
1 parent 97e056b commit 6c45d29

File tree

7 files changed

+138
-18
lines changed

7 files changed

+138
-18
lines changed

src/jit/emitter/emit.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::core::CpuType;
22
use crate::core::CpuType::ARM7;
33
use crate::jit::assembler::block_asm::BlockAsm;
4+
use crate::jit::assembler::{BlockLabel, BlockReg};
45
use crate::jit::inst_threag_regs_handler::{register_restore_spsr, restore_thumb_after_restore_spsr, set_pc_arm_mode};
56
use crate::jit::jit_asm::{JitAsm, JitRuntimeData};
67
use crate::jit::op::Op;
@@ -18,7 +19,8 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
1819
block_asm.start_cond_block(cond);
1920
match op {
2021
Op::B | Op::Bl => self.emit_branch_label(block_asm),
21-
Op::Bx | Op::BlxReg => self.emit_branch_reg(block_asm),
22+
Op::Bx => self.emit_bx(block_asm),
23+
Op::BlxReg => self.emit_blx(block_asm),
2224
Op::Blx => self.emit_blx_label(block_asm),
2325
Op::Mcr | Op::Mrc => self.emit_cp15(block_asm),
2426
Op::MsrRc | Op::MsrIc | Op::MsrRs | Op::MsrIs => self.emit_msr(block_asm),
@@ -99,7 +101,7 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
99101
self._emit_branch_out_metadata(block_asm, true)
100102
}
101103

102-
pub fn emit_flush_cycles<ContinueFn: Fn(&mut Self, &mut BlockAsm), BreakoutFn: Fn(&mut Self, &mut BlockAsm)>(
104+
pub fn emit_flush_cycles<ContinueFn: Fn(&mut Self, &mut BlockAsm, BlockLabel, BlockReg), BreakoutFn: Fn(&mut Self, &mut BlockAsm)>(
103105
&mut self,
104106
block_asm: &mut BlockAsm,
105107
target_pre_cycle_count_sum: u16,
@@ -155,7 +157,7 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
155157
false,
156158
MemoryAmount::Half,
157159
);
158-
continue_fn(self, block_asm);
160+
continue_fn(self, block_asm, breakout_label, runtime_data_addr_reg);
159161

160162
block_asm.label(breakout_label);
161163
breakout_fn(self, block_asm);

src/jit/emitter/emit_branch.rs

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
use crate::core::emu::get_jit;
12
use crate::core::CpuType;
23
use crate::core::CpuType::ARM9;
34
use crate::jit::assembler::block_asm::BlockAsm;
5+
use crate::jit::assembler::BlockOperand;
46
use crate::jit::inst_info::InstInfo;
5-
use crate::jit::jit_asm::JitAsm;
7+
use crate::jit::jit_asm::{JitAsm, JitRuntimeData, BLOCK_LINK_STACK_SIZE};
68
use crate::jit::op::Op;
79
use crate::jit::reg::{reg_reserve, Reg, RegReserve};
8-
use crate::jit::Cond;
10+
use crate::jit::{jit_memory_map, Cond, MemoryAmount, ShiftType};
911

1012
pub enum JitBranchInfo {
1113
Idle,
@@ -80,15 +82,15 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
8082
let branch_info = Self::analyze_branch_label::<THUMB>(&self.jit_buf.insts, self.jit_buf.current_index, cond, self.jit_buf.current_pc, target_pc);
8183

8284
if let JitBranchInfo::Local(target_index) = branch_info {
83-
let target_pre_cycle_count_sum = if target_index == 0 { 0 } else { self.jit_buf.insts_cycle_counts[target_index] };
85+
let target_pre_cycle_count_sum = self.jit_buf.insts_cycle_counts[target_index] - self.jit_buf.insts[target_index].cycle as u16;
8486

8587
let backed_up_cpsr_reg = block_asm.new_reg();
8688
block_asm.mrs_cpsr(backed_up_cpsr_reg);
8789

8890
self.emit_flush_cycles(
8991
block_asm,
9092
target_pre_cycle_count_sum,
91-
|_, block_asm| {
93+
|_, block_asm, _, _| {
9294
block_asm.msr_cpsr(backed_up_cpsr_reg);
9395
block_asm.guest_branch(Cond::AL, target_pc);
9496
},
@@ -113,19 +115,84 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
113115
block_asm.epilogue();
114116
}
115117

116-
pub fn emit_branch_reg(&mut self, block_asm: &mut BlockAsm) {
118+
pub fn emit_bx(&mut self, block_asm: &mut BlockAsm) {
117119
let inst_info = self.jit_buf.current_inst();
118120
let branch_to = *inst_info.operands()[0].as_reg_no_shift().unwrap();
119121

120-
if inst_info.op == Op::BlxReg {
121-
block_asm.mov(Reg::LR, self.jit_buf.current_pc + 4);
122-
}
123122
block_asm.mov(Reg::PC, branch_to);
124123
block_asm.save_context();
125124
self.emit_branch_out_metadata(block_asm);
126125
block_asm.epilogue();
127126
}
128127

128+
pub fn emit_blx(&mut self, block_asm: &mut BlockAsm) {
129+
let inst_info = self.jit_buf.current_inst();
130+
let branch_to = *inst_info.operands()[0].as_reg_no_shift().unwrap();
131+
132+
block_asm.mov(Reg::LR, self.jit_buf.current_pc + 4);
133+
block_asm.mov(Reg::PC, branch_to);
134+
block_asm.save_context();
135+
136+
self.emit_flush_cycles(
137+
block_asm,
138+
0,
139+
|asm, block_asm, breakout_label, runtime_data_addr_reg| {
140+
let block_link_ptr_reg = block_asm.new_reg();
141+
142+
block_asm.transfer_read(block_link_ptr_reg, runtime_data_addr_reg, JitRuntimeData::get_block_link_ptr_offset() as u32, false, MemoryAmount::Byte);
143+
144+
block_asm.cmp(block_link_ptr_reg, BLOCK_LINK_STACK_SIZE as u32);
145+
block_asm.branch(breakout_label, Cond::EQ);
146+
147+
let block_link_stack_ptr_reg = block_asm.new_reg();
148+
block_asm.add(block_link_stack_ptr_reg, runtime_data_addr_reg, JitRuntimeData::get_block_link_stack_offset() as u32);
149+
block_asm.add(block_link_stack_ptr_reg, block_link_stack_ptr_reg, (block_link_ptr_reg.into(), ShiftType::Lsl, BlockOperand::from(3)));
150+
block_asm.transfer_write(Reg::LR, block_link_stack_ptr_reg, 0, false, MemoryAmount::Word);
151+
152+
let return_pre_cycle_count_sum_reg = block_asm.new_reg();
153+
block_asm.mov(return_pre_cycle_count_sum_reg, asm.jit_buf.insts_cycle_counts[asm.jit_buf.current_index] as u32);
154+
block_asm.transfer_write(return_pre_cycle_count_sum_reg, block_link_stack_ptr_reg, 4, false, MemoryAmount::Half);
155+
156+
block_asm.add(block_link_ptr_reg, block_link_ptr_reg, 1);
157+
block_asm.transfer_write(block_link_ptr_reg, runtime_data_addr_reg, JitRuntimeData::get_block_link_ptr_offset() as u32, false, MemoryAmount::Byte);
158+
159+
block_asm.free_reg(return_pre_cycle_count_sum_reg);
160+
block_asm.free_reg(block_link_stack_ptr_reg);
161+
block_asm.free_reg(block_link_ptr_reg);
162+
163+
let target_addr_reg = block_asm.new_reg();
164+
block_asm.mov(target_addr_reg, (branch_to.into(), ShiftType::Lsr, BlockOperand::from(1)));
165+
166+
let map_ptr = get_jit!(asm.emu).jit_memory_map.get_map_ptr::<CPU>();
167+
168+
let map_ptr_reg = block_asm.new_reg();
169+
let map_index_reg = block_asm.new_reg();
170+
let map_entry_base_ptr_reg = block_asm.new_reg();
171+
172+
block_asm.mov(map_ptr_reg, map_ptr as u32);
173+
block_asm.mov(map_index_reg, (target_addr_reg.into(), ShiftType::Lsr, BlockOperand::from(jit_memory_map::BLOCK_SHIFT as u32)));
174+
block_asm.transfer_read(
175+
map_entry_base_ptr_reg,
176+
map_ptr_reg,
177+
(map_index_reg.into(), ShiftType::Lsl, BlockOperand::from(2)),
178+
false,
179+
MemoryAmount::Word,
180+
);
181+
block_asm.bfc(target_addr_reg, jit_memory_map::BLOCK_SHIFT as u8, 32 - jit_memory_map::BLOCK_SHIFT as u8);
182+
block_asm.add(map_entry_base_ptr_reg, map_entry_base_ptr_reg, (target_addr_reg.into(), ShiftType::Lsl, BlockOperand::from(2)));
183+
184+
block_asm.free_reg(map_entry_base_ptr_reg);
185+
block_asm.free_reg(map_index_reg);
186+
block_asm.free_reg(map_ptr_reg);
187+
block_asm.free_reg(target_addr_reg);
188+
},
189+
|asm, block_asm| {
190+
asm.emit_branch_out_metadata(block_asm);
191+
block_asm.epilogue();
192+
},
193+
);
194+
}
195+
129196
pub fn emit_blx_label(&mut self, block_asm: &mut BlockAsm) {
130197
if CPU != ARM9 {
131198
return;

src/jit/inst_branch_handler.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use crate::core::CpuType;
2+
use crate::get_jit_asm_ptr;
3+
4+
pub unsafe extern "C" fn block_link<const CPU: CpuType>(total_cycles: u16) {
5+
let asm = get_jit_asm_ptr::<CPU>();
6+
let runtime_data = &mut (*asm).runtime_data;
7+
runtime_data.block_link_stack
8+
}

src/jit/jit_asm.rs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::jit::reg::Reg;
1111
use crate::jit::reg::{reg_reserve, RegReserve};
1212
use crate::logging::debug_println;
1313
use crate::{get_jit_asm_ptr, DEBUG_LOG, DEBUG_LOG_BRANCH_OUT};
14+
use static_assertions::const_assert_eq;
1415
use std::cell::UnsafeCell;
1516
use std::{mem, ptr};
1617

@@ -45,6 +46,17 @@ impl JitBuf {
4546
}
4647
}
4748

49+
#[repr(C)]
50+
#[derive(Copy, Clone, Default)]
51+
pub struct JitBlockLinkData {
52+
pub desired_lr: u32,
53+
pub return_pre_cycle_count_sum: u16,
54+
}
55+
56+
const_assert_eq!(size_of::<JitBlockLinkData>(), 8);
57+
58+
pub const BLOCK_LINK_STACK_SIZE: usize = 32;
59+
4860
#[repr(C)]
4961
pub struct JitRuntimeData {
5062
pub branch_out_pc: u32,
@@ -53,6 +65,8 @@ pub struct JitRuntimeData {
5365
pub accumulated_cycles: u16,
5466
pub idle_loop: bool,
5567
pub host_sp: usize,
68+
pub block_link_ptr: u8,
69+
pub block_link_stack: [JitBlockLinkData; BLOCK_LINK_STACK_SIZE],
5670
}
5771

5872
impl JitRuntimeData {
@@ -64,18 +78,29 @@ impl JitRuntimeData {
6478
accumulated_cycles: 0,
6579
idle_loop: false,
6680
host_sp: 0,
81+
block_link_ptr: 0,
82+
block_link_stack: [JitBlockLinkData::default(); BLOCK_LINK_STACK_SIZE],
6783
};
84+
6885
let branch_out_pc_ptr = ptr::addr_of!(instance.branch_out_pc) as usize;
6986
let branch_out_total_cycles_ptr = ptr::addr_of!(instance.branch_out_total_cycles) as usize;
7087
let pre_cycle_count_sum_ptr = ptr::addr_of!(instance.pre_cycle_count_sum) as usize;
7188
let accumulated_cycles_ptr = ptr::addr_of!(instance.accumulated_cycles) as usize;
7289
let idle_loop_ptr = ptr::addr_of!(instance.idle_loop) as usize;
7390
let host_sp_ptr = ptr::addr_of!(instance.host_sp) as usize;
91+
let block_link_ptr_ptr = ptr::addr_of!(instance.block_link_ptr) as usize;
92+
let block_link_stack_ptr = ptr::addr_of!(instance.block_link_stack) as usize;
93+
7494
assert_eq!(branch_out_total_cycles_ptr - branch_out_pc_ptr, Self::get_out_total_cycles_offset() as usize);
7595
assert_eq!(pre_cycle_count_sum_ptr - branch_out_pc_ptr, Self::get_pre_cycle_count_sum_offset() as usize);
7696
assert_eq!(accumulated_cycles_ptr - branch_out_pc_ptr, Self::get_accumulated_cycles_offset() as usize);
7797
assert_eq!(idle_loop_ptr - branch_out_pc_ptr, Self::get_idle_loop_offset() as usize);
7898
assert_eq!(host_sp_ptr - branch_out_pc_ptr, Self::get_host_sp_offset() as usize);
99+
assert_eq!(block_link_ptr_ptr - branch_out_pc_ptr, Self::get_block_link_ptr_offset() as usize);
100+
assert_eq!(block_link_stack_ptr - branch_out_pc_ptr, Self::get_block_link_stack_offset() as usize);
101+
102+
assert_eq!(size_of_val(&instance.block_link_stack), 32 * 8);
103+
79104
instance
80105
}
81106

@@ -106,6 +131,14 @@ impl JitRuntimeData {
106131
pub const fn get_host_sp_offset() -> u8 {
107132
Self::get_idle_loop_offset() + 2
108133
}
134+
135+
pub const fn get_block_link_ptr_offset() -> u8 {
136+
Self::get_host_sp_offset() + 4
137+
}
138+
139+
pub const fn get_block_link_stack_offset() -> u8 {
140+
Self::get_block_link_ptr_offset() + 4
141+
}
109142
}
110143

111144
pub extern "C" fn emit_code_block<const CPU: CpuType>() {
@@ -144,20 +177,20 @@ fn emit_code_block_internal<const CPU: CpuType, const THUMB: bool>(guest_pc: u32
144177
assert!(asm.jit_buf.insts_cycle_counts.len() <= u16::MAX as usize, "{CPU:?} {guest_pc:x} {inst_info:?}")
145178
}
146179

147-
// let is_unreturnable_branch = !inst_info.out_regs.is_reserved(Reg::LR) && inst_info.is_uncond_branch() && !inst_info.op.is_labelled_branch();
148-
let is_uncond_branch = inst_info.is_uncond_branch();
180+
let is_unreturnable_branch = !inst_info.out_regs.is_reserved(Reg::LR) && inst_info.is_uncond_branch() && !inst_info.op.is_labelled_branch();
181+
// let is_uncond_branch = inst_info.is_uncond_branch();
149182
let is_unknown = inst_info.op == Op::UnkArm || inst_info.op == Op::UnkThumb;
150183

151184
asm.jit_buf.insts.push(inst_info);
152185

153186
index += if THUMB { 2 } else { 4 };
154-
if is_uncond_branch || is_unknown {
187+
if is_unreturnable_branch || is_unknown {
155188
break;
156189
}
157190
}
158191
}
159192

160-
// unsafe { BLOCK_LOG = true };
193+
unsafe { BLOCK_LOG = true };
161194

162195
let guest_regs_ptr = get_regs_mut!(asm.emu, CPU).get_reg_mut_ptr();
163196
let mut block_asm = unsafe { (*asm.block_asm_buf.get()).new_asm(guest_regs_ptr, ptr::addr_of_mut!((*asm).runtime_data.host_sp)) };
@@ -185,6 +218,7 @@ fn emit_code_block_internal<const CPU: CpuType, const THUMB: bool>(guest_pc: u32
185218
for &opcode in &opcodes {
186219
println!("0x{opcode:x},");
187220
}
221+
todo!()
188222
}
189223
let insert_entry = get_jit_mut!(asm.emu).insert_block::<CPU>(&opcodes, guest_pc);
190224
let jit_entry: extern "C" fn(bool) = unsafe { mem::transmute(insert_entry) };
@@ -218,6 +252,7 @@ fn execute_internal<const CPU: CpuType>(guest_pc: u32) -> u16 {
218252
}
219253
asm.runtime_data.pre_cycle_count_sum = 0;
220254
asm.runtime_data.accumulated_cycles = 0;
255+
asm.runtime_data.block_link_ptr = 0;
221256
get_regs_mut!(asm.emu, CPU).cycle_correction = 0;
222257

223258
jit_entry(true);

src/jit/jit_memory.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub struct JitMemory {
112112
mem_offset: usize,
113113
jit_entries: JitEntries,
114114
jit_live_ranges: JitLiveRanges,
115-
jit_memory_map: JitMemoryMap,
115+
pub jit_memory_map: JitMemoryMap,
116116
}
117117

118118
impl JitMemory {
@@ -154,7 +154,7 @@ impl JitMemory {
154154
}
155155

156156
fn insert(&mut self, opcodes: &[u32]) -> (usize, usize) {
157-
let aligned_size = utils::align_up(opcodes.len() * size_of::<u32>(), *PAGE_SIZE);
157+
let aligned_size = utils::align_up(size_of_val(opcodes), *PAGE_SIZE);
158158
let allocated_offset_addr = self.allocate_block(aligned_size);
159159

160160
utils::write_to_mem_slice(&mut self.mem, allocated_offset_addr, opcodes);

src/jit/jit_memory_map.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::core::CpuType;
33
use crate::jit::jit_memory::{JitEntries, JitEntry, JitLiveRanges, JIT_LIVE_RANGE_PAGE_SIZE_SHIFT};
44
use crate::utils::HeapMemU32;
55

6-
const BLOCK_SHIFT: usize = 13;
6+
pub const BLOCK_SHIFT: usize = 13;
77
const BLOCK_SIZE: usize = 1 << BLOCK_SHIFT;
88
const SIZE: usize = (1 << 31) / BLOCK_SIZE;
99
const LIVE_RANGES_SIZE: usize = 1 << (32 - JIT_LIVE_RANGE_PAGE_SIZE_SHIFT - 5);
@@ -102,4 +102,11 @@ impl JitMemoryMap {
102102
CpuType::ARM7 => self.live_ranges_map_arm7[(addr >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 5)) as usize] as _,
103103
}
104104
}
105+
106+
pub fn get_map_ptr<const CPU: CpuType>(&self) -> *const JitEntry {
107+
match CPU {
108+
CpuType::ARM9 => self.map_arm9.as_ptr() as _,
109+
CpuType::ARM7 => self.map_arm7.as_ptr() as _,
110+
}
111+
}
105112
}

src/jit/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub mod jit_memory;
1717
pub mod op;
1818
pub mod reg;
1919
mod jit_memory_map;
20+
mod inst_branch_handler;
2021

2122
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2223
#[repr(u8)]

0 commit comments

Comments
 (0)