11use crate :: bitset:: Bitset ;
22use crate :: jit:: assembler:: arm:: branch_assembler:: B ;
33use crate :: jit:: assembler:: basic_block:: BasicBlock ;
4- use crate :: jit:: assembler:: block_inst:: { BlockAluOp , BlockAluSetCond , BlockSystemRegOp , BlockTransferOp , BranchEncoding , GuestInstInfo } ;
4+ use crate :: jit:: assembler:: block_inst:: { BlockAluOp , BlockAluSetCond , BlockInst , BlockSystemRegOp , BlockTransferOp , BranchEncoding , GuestInstInfo } ;
55use crate :: jit:: assembler:: block_inst_list:: BlockInstList ;
66use crate :: jit:: assembler:: block_reg_allocator:: ALLOCATION_REGS ;
77use crate :: jit:: assembler:: block_reg_set:: BlockRegSet ;
8- use crate :: jit:: assembler:: { BlockAsmBuf , BlockInst , BlockLabel , BlockOperand , BlockOperandShift , BlockReg , ANY_REG_LIMIT } ;
8+ use crate :: jit:: assembler:: { BlockAsmBuf , BlockInstKind , BlockLabel , BlockOperand , BlockOperandShift , BlockReg , ANY_REG_LIMIT } ;
99use crate :: jit:: inst_info:: InstInfo ;
1010use crate :: jit:: reg:: { Reg , RegReserve } ;
1111use crate :: jit:: { Cond , MemoryAmount , ShiftType } ;
@@ -57,7 +57,7 @@ pub struct BlockAsm<'a> {
5757 tmp_shift_imm_reg : BlockReg ,
5858 tmp_func_call_reg : BlockReg ,
5959
60- cond_block_end_label_stack : Vec < BlockLabel > ,
60+ cond_block_end_label_stack : Vec < ( BlockLabel , Cond , usize ) > ,
6161
6262 is_common_fun : bool ,
6363 host_sp_ptr : * mut usize ,
@@ -102,7 +102,7 @@ impl<'a> BlockAsm<'a> {
102102 inst_insert_index : None ,
103103 } ;
104104
105- instance. buf . insts . push ( BlockInst :: Prologue ) ;
105+ instance. insert_inst ( BlockInstKind :: Prologue ) ;
106106
107107 // First argument is store_host_sp: bool
108108 if !is_common_fun {
@@ -125,11 +125,11 @@ impl<'a> BlockAsm<'a> {
125125 instance
126126 }
127127
128- fn insert_inst ( & mut self , inst : BlockInst ) {
128+ fn insert_inst ( & mut self , inst : impl Into < BlockInst > ) {
129129 match self . inst_insert_index {
130- None => self . buf . insts . push ( inst) ,
130+ None => self . buf . insts . push ( inst. into ( ) ) ,
131131 Some ( index) => {
132- self . buf . insts . insert ( index, inst) ;
132+ self . buf . insts . insert ( index, inst. into ( ) ) ;
133133 self . inst_insert_index = Some ( index + 1 ) ;
134134 }
135135 }
@@ -226,7 +226,7 @@ impl<'a> BlockAsm<'a> {
226226 fn add_op3 ( & mut self , op : BlockAluOp , op0 : BlockReg , op1 : BlockReg , mut op2 : BlockOperandShift , set_cond : BlockAluSetCond , thumb_pc_aligned : bool ) {
227227 self . check_alu_imm_limit ( & mut op2) ;
228228 self . check_imm_shift_limit ( & mut op2) ;
229- self . insert_inst ( BlockInst :: Alu3 {
229+ self . insert_inst ( BlockInstKind :: Alu3 {
230230 op,
231231 operands : [ op0. into ( ) , op1. into ( ) , op2] ,
232232 set_cond,
@@ -237,7 +237,7 @@ impl<'a> BlockAsm<'a> {
237237 fn add_op2_op1 ( & mut self , op : BlockAluOp , op1 : BlockReg , mut op2 : BlockOperandShift , set_cond : BlockAluSetCond , thumb_pc_aligned : bool ) {
238238 self . check_alu_imm_limit ( & mut op2) ;
239239 self . check_imm_shift_limit ( & mut op2) ;
240- self . insert_inst ( BlockInst :: Alu2Op1 {
240+ self . insert_inst ( BlockInstKind :: Alu2Op1 {
241241 op,
242242 operands : [ op1. into ( ) , op2] ,
243243 set_cond,
@@ -250,7 +250,7 @@ impl<'a> BlockAsm<'a> {
250250 self . check_alu_imm_limit ( & mut op2) ;
251251 }
252252 self . check_imm_shift_limit ( & mut op2) ;
253- self . insert_inst ( BlockInst :: Alu2Op0 {
253+ self . insert_inst ( BlockInstKind :: Alu2Op0 {
254254 op,
255255 operands : [ op0. into ( ) , op2] ,
256256 set_cond,
@@ -289,7 +289,7 @@ impl<'a> BlockAsm<'a> {
289289 op2 = self . tmp_operand_imm_reg . into ( ) ;
290290 }
291291 self . check_imm_shift_limit ( & mut op2) ;
292- self . insert_inst ( BlockInst :: Transfer {
292+ self . insert_inst ( BlockInstKind :: Transfer {
293293 op,
294294 operands : [ op0. into ( ) . into ( ) , op1. into ( ) . into ( ) , op2] ,
295295 signed,
@@ -307,7 +307,7 @@ impl<'a> BlockAsm<'a> {
307307 }
308308
309309 pub fn transfer_read_multiple ( & mut self , operand : impl Into < BlockReg > , regs : RegReserve , write_back : bool , pre : bool , add_to_base : bool ) {
310- self . insert_inst ( BlockInst :: TransferMultiple {
310+ self . insert_inst ( BlockInstKind :: TransferMultiple {
311311 op : BlockTransferOp :: Read ,
312312 operand : operand. into ( ) ,
313313 regs,
@@ -318,7 +318,7 @@ impl<'a> BlockAsm<'a> {
318318 }
319319
320320 pub fn transfer_write_multiple ( & mut self , operand : impl Into < BlockReg > , regs : RegReserve , write_back : bool , pre : bool , add_to_base : bool ) {
321- self . insert_inst ( BlockInst :: TransferMultiple {
321+ self . insert_inst ( BlockInstKind :: TransferMultiple {
322322 op : BlockTransferOp :: Write ,
323323 operand : operand. into ( ) ,
324324 regs,
@@ -329,33 +329,33 @@ impl<'a> BlockAsm<'a> {
329329 }
330330
331331 pub fn mrs_cpsr ( & mut self , operand : impl Into < BlockReg > ) {
332- self . insert_inst ( BlockInst :: SystemReg {
332+ self . insert_inst ( BlockInstKind :: SystemReg {
333333 op : BlockSystemRegOp :: Mrs ,
334334 operand : operand. into ( ) . into ( ) ,
335335 } )
336336 }
337337
338338 pub fn msr_cpsr ( & mut self , operand : impl Into < BlockOperand > ) {
339- self . insert_inst ( BlockInst :: SystemReg {
339+ self . insert_inst ( BlockInstKind :: SystemReg {
340340 op : BlockSystemRegOp :: Msr ,
341341 operand : operand. into ( ) ,
342342 } )
343343 }
344344
345345 pub fn bfc ( & mut self , operand : impl Into < BlockReg > , lsb : u8 , width : u8 ) {
346- self . insert_inst ( BlockInst :: Bfc { operand : operand. into ( ) , lsb, width } )
346+ self . insert_inst ( BlockInstKind :: Bfc { operand : operand. into ( ) , lsb, width } )
347347 }
348348
349349 pub fn bfi ( & mut self , op0 : impl Into < BlockReg > , op1 : impl Into < BlockReg > , lsb : u8 , width : u8 ) {
350- self . insert_inst ( BlockInst :: Bfi {
350+ self . insert_inst ( BlockInstKind :: Bfi {
351351 operands : [ op0. into ( ) , op1. into ( ) ] ,
352352 lsb,
353353 width,
354354 } )
355355 }
356356
357357 pub fn muls_guest_thumb_pc_aligned ( & mut self , op0 : impl Into < BlockReg > , op1 : impl Into < BlockReg > , op2 : impl Into < BlockOperandShift > ) {
358- self . insert_inst ( BlockInst :: Mul {
358+ self . insert_inst ( BlockInstKind :: Mul {
359359 operands : [ op0. into ( ) . into ( ) , op1. into ( ) . into ( ) , op2. into ( ) ] ,
360360 set_cond : BlockAluSetCond :: HostGuest ,
361361 thumb_pc_aligned : true ,
@@ -366,30 +366,29 @@ impl<'a> BlockAsm<'a> {
366366 if !self . used_labels . insert ( label. 0 ) {
367367 panic ! ( "{label:?} was already added" ) ;
368368 }
369- self . insert_inst ( BlockInst :: Label { label, guest_pc : None } )
369+ self . insert_inst ( BlockInstKind :: Label { label, guest_pc : None } )
370370 }
371371
372372 pub fn branch ( & mut self , label : BlockLabel , cond : Cond ) {
373- self . insert_inst ( BlockInst :: Branch { label, cond , block_index : 0 } )
373+ self . insert_inst ( BlockInst :: new ( cond , BlockInstKind :: Branch { label, block_index : 0 } ) )
374374 }
375375
376376 pub fn save_context ( & mut self ) {
377- self . insert_inst ( BlockInst :: SaveContext {
377+ self . insert_inst ( BlockInstKind :: SaveContext {
378378 thread_regs_addr_reg : self . thread_regs_addr_reg ,
379- tmp_guest_cpsr_reg : self . tmp_guest_cpsr_reg ,
380379 } ) ;
381380 }
382381
383382 pub fn save_reg ( & mut self , guest_reg : Reg ) {
384- self . insert_inst ( BlockInst :: SaveReg {
383+ self . insert_inst ( BlockInstKind :: SaveReg {
385384 guest_reg,
386385 reg_mapped : BlockReg :: from ( guest_reg) ,
387386 thread_regs_addr_reg : self . thread_regs_addr_reg ,
388387 } ) ;
389388 }
390389
391390 pub fn restore_reg ( & mut self , guest_reg : Reg ) {
392- self . insert_inst ( BlockInst :: RestoreReg {
391+ self . insert_inst ( BlockInstKind :: RestoreReg {
393392 guest_reg,
394393 reg_mapped : BlockReg :: from ( guest_reg) ,
395394 thread_regs_addr_reg : self . thread_regs_addr_reg ,
@@ -401,12 +400,12 @@ impl<'a> BlockAsm<'a> {
401400 let host_sp_addr_reg = self . thread_regs_addr_reg ;
402401 self . mov ( host_sp_addr_reg, self . host_sp_ptr as u32 ) ;
403402 self . load_u32 ( BlockReg :: Fixed ( Reg :: SP ) , host_sp_addr_reg, 0 ) ;
404- self . buf . insts . push ( BlockInst :: Epilogue { restore_all_regs : true } ) ;
403+ self . insert_inst ( BlockInstKind :: Epilogue { restore_all_regs : true } ) ;
405404 }
406405
407406 pub fn epilogue_previous_block ( & mut self ) {
408407 self . add ( BlockReg :: Fixed ( Reg :: SP ) , BlockReg :: Fixed ( Reg :: SP ) , ANY_REG_LIMIT as u32 * 4 ) ;
409- self . buf . insts . push ( BlockInst :: Epilogue { restore_all_regs : false } ) ;
408+ self . insert_inst ( BlockInstKind :: Epilogue { restore_all_regs : false } ) ;
410409 }
411410
412411 pub fn call ( & mut self , func : impl Into < BlockOperand > ) {
@@ -478,7 +477,7 @@ impl<'a> BlockAsm<'a> {
478477 ) {
479478 let args = self . handle_call_args ( arg0, arg1, arg2, arg3) ;
480479 self . mov ( self . tmp_func_call_reg , func. into ( ) ) ;
481- self . insert_inst ( BlockInst :: Call {
480+ self . insert_inst ( BlockInstKind :: Call {
482481 func_reg : self . tmp_func_call_reg ,
483482 args : [
484483 args[ 0 ] . map ( |_| BlockReg :: Fixed ( Reg :: R0 ) ) ,
@@ -520,7 +519,7 @@ impl<'a> BlockAsm<'a> {
520519 has_return : bool ,
521520 ) {
522521 let args = self . handle_call_args ( arg0, arg1, arg2, arg3) ;
523- self . insert_inst ( BlockInst :: CallCommon {
522+ self . insert_inst ( BlockInstKind :: CallCommon {
524523 mem_offset : offset,
525524 args : [
526525 args[ 0 ] . map ( |_| BlockReg :: Fixed ( Reg :: R0 ) ) ,
@@ -533,12 +532,12 @@ impl<'a> BlockAsm<'a> {
533532 }
534533
535534 pub fn bkpt ( & mut self , id : u16 ) {
536- self . insert_inst ( BlockInst :: Bkpt ( id) ) ;
535+ self . insert_inst ( BlockInstKind :: Bkpt ( id) ) ;
537536 }
538537
539538 pub fn find_guest_pc_inst_index ( & self , guest_pc_to_find : u32 ) -> Option < usize > {
540539 for ( i, inst) in self . buf . insts . iter ( ) . enumerate ( ) . rev ( ) {
541- if let BlockInst :: GuestPc ( guest_pc) = inst {
540+ if let BlockInstKind :: GuestPc ( guest_pc) = & inst. kind {
542541 if * guest_pc == guest_pc_to_find {
543542 return Some ( i) ;
544543 }
@@ -548,7 +547,7 @@ impl<'a> BlockAsm<'a> {
548547 }
549548
550549 pub fn guest_pc ( & mut self , pc : u32 ) {
551- self . insert_inst ( BlockInst :: GuestPc ( pc) ) ;
550+ self . insert_inst ( BlockInstKind :: GuestPc ( pc) ) ;
552551 }
553552
554553 pub fn guest_branch ( & mut self , cond : Cond , target_pc : u32 ) {
@@ -560,11 +559,11 @@ impl<'a> BlockAsm<'a> {
560559 }
561560 Some ( label) => * label,
562561 } ;
563- self . insert_inst ( BlockInst :: Branch { label, cond , block_index : 0 } ) ;
562+ self . insert_inst ( BlockInst :: new ( cond , BlockInstKind :: Branch { label, block_index : 0 } ) ) ;
564563 }
565564
566565 pub fn generic_guest_inst ( & mut self , inst_info : & mut InstInfo ) {
567- self . insert_inst ( BlockInst :: GenericGuestInst {
566+ self . insert_inst ( BlockInstKind :: GenericGuestInst {
568567 inst : GuestInstInfo :: new ( inst_info) ,
569568 regs_mapping : [
570569 BlockReg :: from ( Reg :: R0 ) ,
@@ -593,13 +592,20 @@ impl<'a> BlockAsm<'a> {
593592 if cond != Cond :: AL {
594593 let label = self . new_label ( ) ;
595594 self . branch ( label, !cond) ;
596- self . cond_block_end_label_stack . push ( label) ;
595+ self . cond_block_end_label_stack . push ( ( label, cond , self . buf . insts . len ( ) ) ) ;
597596 }
598597 }
599598
600599 pub fn end_cond_block ( & mut self ) {
601- if let Some ( label) = self . cond_block_end_label_stack . pop ( ) {
602- self . label ( label) ;
600+ if let Some ( ( label, cond, start_index) ) = self . cond_block_end_label_stack . pop ( ) {
601+ let cond_block_size = self . buf . insts . len ( ) - start_index;
602+ let ( _, outputs) = self . buf . insts [ start_index] . get_io ( ) ;
603+ if cond_block_size == 1 && self . buf . insts [ start_index] . cond == Cond :: AL && !outputs. contains ( BlockReg :: Fixed ( Reg :: CPSR ) ) && !outputs. contains ( Reg :: CPSR . into ( ) ) {
604+ self . buf . insts [ start_index] . cond = cond;
605+ self . buf . insts . remove ( start_index - 1 ) ;
606+ } else {
607+ self . label ( label) ;
608+ }
603609 }
604610 }
605611
@@ -610,29 +616,30 @@ impl<'a> BlockAsm<'a> {
610616 let mut current_node = self . insts_link . root ;
611617 while !current_node. is_null ( ) {
612618 let i = BlockInstList :: deref ( current_node) . value ;
613- if let BlockInst :: GuestPc ( pc) = & self . buf . insts [ i] {
619+ if let BlockInstKind :: GuestPc ( pc) = & self . buf . insts [ i] . kind {
614620 if let Some ( guest_label) = self . buf . guest_branches_mapping . get ( pc) {
615- self . buf . insts [ i] = BlockInst :: Label {
621+ self . buf . insts [ i] = BlockInstKind :: Label {
616622 label : * guest_label,
617623 guest_pc : Some ( * pc) ,
618- } ;
624+ }
625+ . into ( ) ;
619626 }
620627 }
621628
622- if let BlockInst :: Label { label, guest_pc } = self . buf . insts [ i] {
629+ if let BlockInstKind :: Label { label, guest_pc } = & self . buf . insts [ i] . kind {
623630 if let Some ( ( p_label, p_guest_pc) ) = previous_label {
624- let replace_guest_pc = p_guest_pc. or ( guest_pc) ;
631+ let replace_guest_pc = p_guest_pc. or ( * guest_pc) ;
625632 previous_label = Some ( ( p_label, replace_guest_pc) ) ;
626633 let previous_node = BlockInstList :: deref ( current_node) . previous ;
627634 let previous_i = BlockInstList :: deref ( previous_node) . value ;
628- if let BlockInst :: Label { guest_pc, .. } = & mut self . buf . insts [ previous_i] {
629- * guest_pc = replace_guest_pc;
630- }
631635 self . insts_link . remove_entry ( current_node) ;
632636 label_aliases. insert ( label. 0 , p_label. 0 ) ;
633637 current_node = previous_node;
638+ if let BlockInstKind :: Label { guest_pc, .. } = & mut self . buf . insts [ previous_i] . kind {
639+ * guest_pc = replace_guest_pc;
640+ }
634641 } else {
635- previous_label = Some ( ( label, guest_pc) ) ;
642+ previous_label = Some ( ( * label, * guest_pc) ) ;
636643 }
637644 } else {
638645 previous_label = None
@@ -706,8 +713,8 @@ impl<'a> BlockAsm<'a> {
706713 while !current_node. is_null ( ) {
707714 let i = BlockInstList :: deref ( current_node) . value ;
708715
709- match & mut self . buf . insts [ i] {
710- BlockInst :: Label { label, .. } => {
716+ match & mut self . buf . insts [ i] . kind {
717+ BlockInstKind :: Label { label, .. } => {
711718 let label = * label;
712719 // block_start_entry can be the same as current_node, when the previous iteration ended with a branch
713720 if basic_block_start != current_node {
@@ -719,7 +726,7 @@ impl<'a> BlockAsm<'a> {
719726 }
720727 last_label = Some ( label) ;
721728 }
722- BlockInst :: Branch { label, .. } => {
729+ BlockInstKind :: Branch { label, .. } => {
723730 if let Some ( alias) = label_aliases. get ( & label. 0 ) {
724731 label. 0 = * alias;
725732 }
@@ -730,7 +737,7 @@ impl<'a> BlockAsm<'a> {
730737 }
731738 last_label = None ;
732739 }
733- BlockInst :: Call { has_return : false , .. } | BlockInst :: Epilogue { .. } => {
740+ BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => {
734741 basic_blocks. push ( BasicBlock :: new ( self , basic_block_start, current_node) ) ;
735742 basic_block_start = BlockInstList :: deref ( current_node) . next ;
736743 if let Some ( last_label) = last_label {
@@ -755,17 +762,18 @@ impl<'a> BlockAsm<'a> {
755762 // Link blocks
756763 for ( i, basic_block) in basic_blocks. iter_mut ( ) . enumerate ( ) {
757764 let last_inst_index = BlockInstList :: deref ( basic_block. block_entry_end ) . value ;
758- match & mut self . buf . insts [ last_inst_index] {
759- BlockInst :: Branch { label, cond, block_index, .. } => {
765+ let cond = self . buf . insts [ last_inst_index] . cond ;
766+ match & mut self . buf . insts [ last_inst_index] . kind {
767+ BlockInstKind :: Branch { label, block_index, .. } => {
760768 let labelled_block_index = basic_block_label_mapping. get ( & label. 0 ) . unwrap ( ) ;
761769 basic_block. exit_blocks . push ( * labelled_block_index) ;
762770 * block_index = * labelled_block_index;
763- if * cond != Cond :: AL && i + 1 < basic_blocks_len {
771+ if cond != Cond :: AL && i + 1 < basic_blocks_len {
764772 basic_block. exit_blocks . push ( i + 1 ) ;
765773 }
766774 }
767775 // Don't add exit when last command in basic block is a breakout
768- BlockInst :: Call { has_return : false , .. } | BlockInst :: Epilogue { .. } => {
776+ BlockInstKind :: Call { has_return : false , .. } | BlockInstKind :: Epilogue { .. } => {
769777 if i + 1 < basic_blocks_len {
770778 basic_block. exit_blocks . push ( i + 1 ) ;
771779 }
@@ -793,12 +801,12 @@ impl<'a> BlockAsm<'a> {
793801 let mut basic_block_start_pc = block_start_pc;
794802 let mut current_node = basic_block. block_entry_start ;
795803 while !current_node. is_null ( ) {
796- match & self . buf . insts [ BlockInstList :: deref ( current_node) . value ] {
797- BlockInst :: Label { guest_pc : Some ( pc) , .. } => {
804+ match & self . buf . insts [ BlockInstList :: deref ( current_node) . value ] . kind {
805+ BlockInstKind :: Label { guest_pc : Some ( pc) , .. } => {
798806 basic_block_start_pc = * pc;
799807 break ;
800808 }
801- BlockInst :: GuestPc ( pc) => {
809+ BlockInstKind :: GuestPc ( pc) => {
802810 basic_block_start_pc = * pc;
803811 break ;
804812 }
0 commit comments