@@ -32,51 +32,54 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
3232 } ;
3333
3434 block_asm. start_cond_block ( cond) ;
35- self . emit_branch_label_common :: < true > ( block_asm, target_pc, cond, false ) ;
35+ self . emit_branch_label_common :: < true > ( block_asm, target_pc | 1 , cond, false ) ;
3636 block_asm. end_cond_block ( ) ;
3737 }
3838
39- pub fn emit_bl_setup_thumb ( & mut self , block_asm : & mut BlockAsm ) {
40- let inst_info = self . jit_buf . current_inst ( ) ;
41-
42- let op0 = * inst_info. operands ( ) [ 0 ] . as_imm ( ) . unwrap ( ) as i32 ;
43- let lr = ( self . jit_buf . current_pc as i32 + 4 + op0) as u32 ;
44-
45- block_asm. mov ( Reg :: LR , lr) ;
39+ pub fn emit_bl_setup_thumb ( & mut self ) {
40+ let next_inst_info = & self . jit_buf . insts [ self . jit_buf . current_index + 1 ] ;
41+ assert ! ( next_inst_info. op == Op :: BlOffT || next_inst_info. op == Op :: BlxOffT )
4642 }
4743
4844 pub fn emit_bl_thumb ( & mut self , block_asm : & mut BlockAsm ) {
49- let inst_info = self . jit_buf . current_inst ( ) ;
45+ let previous_inst_info = & self . jit_buf . insts [ self . jit_buf . current_index - 1 ] ;
46+ assert_eq ! ( previous_inst_info. op, Op :: BlSetupT ) ;
5047
51- let op0 = * inst_info . operands ( ) [ 0 ] . as_imm ( ) . unwrap ( ) ;
52- let lr = self . jit_buf . current_pc + 2 ;
48+ let relative_pc = * previous_inst_info . operands ( ) [ 0 ] . as_imm ( ) . unwrap ( ) as i32 + 4 ;
49+ let mut target_pc = ( self . jit_buf . current_pc as i32 - 2 + relative_pc ) as u32 ;
5350
54- let target_pc_reg = block_asm . new_reg ( ) ;
55- block_asm . add ( target_pc_reg , Reg :: LR , op0) ;
51+ let inst_info = self . jit_buf . current_inst ( ) ;
52+ let op0 = * inst_info . operands ( ) [ 0 ] . as_imm ( ) . unwrap ( ) ;
5653
57- block_asm . mov ( Reg :: LR , lr | 1 ) ;
54+ target_pc += op0 ;
5855
5956 if inst_info. op == Op :: BlxOffT {
60- block_asm . bic ( target_pc_reg , target_pc_reg , 0x1 ) ;
57+ target_pc &= ! 1 ;
6158 } else {
62- block_asm . orr ( target_pc_reg , target_pc_reg , 0x1 ) ;
59+ target_pc |= 1 ;
6360 }
6461
65- self . emit_branch_reg_common ( block_asm , target_pc_reg , true ) ;
66- block_asm . free_reg ( target_pc_reg ) ;
62+ block_asm . mov ( Reg :: LR , ( self . jit_buf . current_pc + 2 ) | 1 ) ;
63+ self . emit_branch_label_common :: < true > ( block_asm , target_pc , Cond :: AL , true ) ;
6764 }
6865
6966 pub fn emit_bx_thumb ( & mut self , block_asm : & mut BlockAsm ) {
7067 let inst_info = self . jit_buf . current_inst ( ) ;
7168
7269 let op0 = * inst_info. operands ( ) [ 0 ] . as_reg_no_shift ( ) . unwrap ( ) ;
7370
74- if inst_info. op == Op :: BlxRegT {
75- block_asm. mov ( Reg :: LR , self . jit_buf . current_pc + 3 ) ;
76- }
7771 block_asm. mov ( Reg :: PC , op0) ;
7872 block_asm. save_context ( ) ;
7973 self . emit_branch_out_metadata ( block_asm) ;
8074 block_asm. epilogue ( ) ;
8175 }
76+
77+ pub fn emit_blx_thumb ( & mut self , block_asm : & mut BlockAsm ) {
78+ let inst_info = self . jit_buf . current_inst ( ) ;
79+
80+ let op0 = * inst_info. operands ( ) [ 0 ] . as_reg_no_shift ( ) . unwrap ( ) ;
81+
82+ block_asm. mov ( Reg :: LR , self . jit_buf . current_pc + 3 ) ;
83+ self . emit_branch_reg_common ( block_asm, op0. into ( ) , true ) ;
84+ }
8285}
0 commit comments