1+ use crate :: core:: emu:: get_jit;
12use crate :: core:: CpuType ;
23use crate :: core:: CpuType :: ARM9 ;
34use crate :: jit:: assembler:: block_asm:: BlockAsm ;
5+ use crate :: jit:: assembler:: BlockOperand ;
46use crate :: jit:: inst_info:: InstInfo ;
5- use crate :: jit:: jit_asm:: JitAsm ;
7+ use crate :: jit:: jit_asm:: { JitAsm , JitRuntimeData , BLOCK_LINK_STACK_SIZE } ;
68use crate :: jit:: op:: Op ;
79use crate :: jit:: reg:: { reg_reserve, Reg , RegReserve } ;
8- use crate :: jit:: Cond ;
10+ use crate :: jit:: { jit_memory_map , Cond , MemoryAmount , ShiftType } ;
911
1012pub 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 ;
0 commit comments