Skip to content

Commit af82fd0

Browse files
committed
WIP
1 parent 97e056b commit af82fd0

File tree

7 files changed

+145
-25
lines changed

7 files changed

+145
-25
lines changed

src/jit/assembler/block_asm.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ impl<'a> BlockAsm<'a> {
513513

514514
if let BlockInst::Label { label, guest_pc } = self.buf.insts[i] {
515515
if let Some((p_label, p_guest_pc)) = previous_label {
516-
let replace_guest_pc = p_guest_pc.or_else(|| guest_pc);
516+
let replace_guest_pc = p_guest_pc.or(guest_pc);
517517
previous_label = Some((p_label, replace_guest_pc));
518518
let previous_node = BlockInstList::deref(current_node).previous;
519519
let previous_i = BlockInstList::deref(previous_node).value;
@@ -559,6 +559,7 @@ impl<'a> BlockAsm<'a> {
559559
}
560560
}
561561
if cycle {
562+
println!("ordering {block_i} cycle");
562563
ordering[*ordering_end] = block_i;
563564
*ordering_end -= 1;
564565
} else {
@@ -671,11 +672,9 @@ impl<'a> BlockAsm<'a> {
671672
let mut current_node = basic_block.block_entry_start;
672673
while !current_node.is_null() {
673674
match &self.buf.insts[BlockInstList::deref(current_node).value] {
674-
BlockInst::Label { guest_pc, .. } => {
675-
if let Some(pc) = guest_pc {
676-
basic_block_start_pc = *pc;
677-
break;
678-
}
675+
BlockInst::Label { guest_pc: Some(pc), .. } => {
676+
basic_block_start_pc = *pc;
677+
break;
679678
}
680679
BlockInst::GuestPc(pc) => {
681680
basic_block_start_pc = *pc;
@@ -753,6 +752,11 @@ impl<'a> BlockAsm<'a> {
753752

754753
let mut reg_intervals = Self::assemble_intervals(&basic_blocks, &basic_blocks_order);
755754

755+
if unsafe { BLOCK_LOG } {
756+
println!("reg intervals {reg_intervals:?} ");
757+
println!("block ordering {basic_blocks_order:?}");
758+
}
759+
756760
self.buf.reg_allocator.global_mapping.clear();
757761
let mut free_regs = block_reg_allocator::ALLOCATION_REGS;
758762
while !free_regs.is_empty() {

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: 80 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,89 @@ 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+
let entry_fn_reg = block_asm.new_reg();
185+
block_asm.transfer_read(entry_fn_reg, map_entry_base_ptr_reg, 0, false, MemoryAmount::Word);
186+
block_asm.call1(entry_fn_reg, 0);
187+
188+
block_asm.free_reg(entry_fn_reg);
189+
block_asm.free_reg(map_entry_base_ptr_reg);
190+
block_asm.free_reg(map_index_reg);
191+
block_asm.free_reg(map_ptr_reg);
192+
block_asm.free_reg(target_addr_reg);
193+
},
194+
|asm, block_asm| {
195+
asm.emit_branch_out_metadata(block_asm);
196+
block_asm.epilogue();
197+
},
198+
);
199+
}
200+
129201
pub fn emit_blx_label(&mut self, block_asm: &mut BlockAsm) {
130202
if CPU != ARM9 {
131203
return;

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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ mod inst_mem_handler;
1414
mod inst_threag_regs_handler;
1515
pub mod jit_asm;
1616
pub mod jit_memory;
17+
mod jit_memory_map;
1718
pub mod op;
1819
pub mod reg;
19-
mod jit_memory_map;
2020

2121
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2222
#[repr(u8)]

0 commit comments

Comments
 (0)