@@ -533,8 +533,37 @@ FORCE_INLINE bool insn_is_unconditional_branch(uint8_t opcode)
533533    case  rv_insn_cebreak :
534534#endif 
535535        return  true;
536+     default :
537+         return  false;
538+     }
539+ }
540+ 
541+ FORCE_INLINE  bool  insn_is_direct_branch (uint8_t  opcode )
542+ {
543+     switch  (opcode ) {
544+     case  rv_insn_jal :
545+ #if  RV32_HAS (EXT_C )
546+     case  rv_insn_cjal :
547+     case  rv_insn_cj :
548+ #endif 
549+         return  true;
550+     default :
551+         return  false;
552+     }
553+ }
554+ 
555+ FORCE_INLINE  bool  insn_is_indirect_branch (uint8_t  opcode )
556+ {
557+     switch  (opcode ) {
558+     case  rv_insn_jalr :
559+ #if  RV32_HAS (EXT_C )
560+     case  rv_insn_cjalr :
561+     case  rv_insn_cjr :
562+ #endif 
563+         return  true;
564+     default :
565+         return  false;
536566    }
537-     return  false;
538567}
539568
540569static  void  block_translate (riscv_t  * rv , block_t  * block )
@@ -571,11 +600,7 @@ static void block_translate(riscv_t *rv, block_t *block)
571600#endif 
572601        /* stop on branch */ 
573602        if  (insn_is_branch (ir -> opcode )) {
574-             if  (ir -> opcode  ==  rv_insn_jalr 
575- #if  RV32_HAS (EXT_C )
576-                 ||  ir -> opcode  ==  rv_insn_cjalr  ||  ir -> opcode  ==  rv_insn_cjr 
577- #endif 
578-             ) {
603+             if  (insn_is_indirect_branch (ir -> opcode )) {
579604                ir -> branch_table  =  calloc (1 , sizeof (branch_history_table_t ));
580605                assert (ir -> branch_table );
581606                memset (ir -> branch_table -> PC , -1 ,
@@ -768,95 +793,89 @@ static block_t *block_find_or_translate(riscv_t *rv)
768793#if  !RV32_HAS (JIT )
769794    block_map_t  * map  =  & rv -> block_map ;
770795    /* lookup the next block in the block map */ 
771-     block_t  * next  =  block_find (map , rv -> PC );
796+     block_t  * next_blk  =  block_find (map , rv -> PC );
772797#else 
773798    /* lookup the next block in the block cache */ 
774-     block_t  * next  =  (block_t  * ) cache_get (rv -> block_cache , rv -> PC , true);
799+     /* 
800+      * The function "cache_get()" gets the cached block by the given "key (PC)". 
801+      * In system simulation, the returned block might be dropped because it is 
802+      * not the one from the current process (by checking SATP CSR register). 
803+      */ 
804+     block_t  * next_blk  =  (block_t  * ) cache_get (rv -> block_cache , rv -> PC , true);
775805#endif 
776806
777-     if  (!next ) {
807+     if  (next_blk )
808+         return  next_blk ;
809+ 
778810#if  !RV32_HAS (JIT )
779-         if  (map -> size  *  1.25  >  map -> block_capacity ) {
780-             block_map_clear (rv );
781-             prev  =  NULL ;
782-         }
811+     /* clear block list if it is going to be filled */ 
812+     if  (map -> size  *  1.25  >  map -> block_capacity ) {
813+         block_map_clear (rv );
814+         prev  =  NULL ;
815+     }
783816#endif 
784-         /* allocate a new block */ 
785-         next  =  block_alloc (rv );
786-         block_translate (rv , next );
817+     /* allocate a new block */ 
818+     next_blk  =  block_alloc (rv );
819+ 
820+     block_translate (rv , next_blk );
787821
788-          optimize_constant (rv , next );
822+     optimize_constant (rv , next_blk );
789823#if  RV32_HAS (GDBSTUB )
790-          if  (likely (!rv -> debug_mode ))
824+     if  (likely (!rv -> debug_mode ))
791825#endif 
792-              /* macro operation fusion */ 
793-              match_pattern (rv , next );
826+         /* macro operation fusion */ 
827+         match_pattern (rv , next_blk );
794828
795829#if  !RV32_HAS (JIT )
796-          /* insert the block into block map */ 
797-          block_insert (& rv -> block_map , next );
830+     /* insert the block into block map */ 
831+     block_insert (& rv -> block_map , next_blk );
798832#else 
799-         /* insert the block into block cache */ 
800-         block_t  * delete_target  =  cache_put (rv -> block_cache , rv -> PC , & (* next ));
801-         if  (delete_target ) {
802-             if  (prev  ==  delete_target )
803-                 prev  =  NULL ;
804-             chain_entry_t  * entry , * safe ;
805-             /* correctly remove deleted block from its chained block */ 
806-             rv_insn_t  * taken  =  delete_target -> ir_tail -> branch_taken ,
807-                       * untaken  =  delete_target -> ir_tail -> branch_untaken ;
808-             if  (taken  &&  taken -> pc  !=  delete_target -> pc_start ) {
809-                 block_t  * target  =  cache_get (rv -> block_cache , taken -> pc , false);
810-                 bool  flag  =  false;
811-                 list_for_each_entry_safe  (entry , safe , & target -> list , list ) {
812-                     if  (entry -> block  ==  delete_target ) {
813-                         list_del_init (& entry -> list );
814-                         mpool_free (rv -> chain_entry_mp , entry );
815-                         flag  =  true;
816-                     }
817-                 }
818-                 assert (flag );
819-             }
820-             if  (untaken  &&  untaken -> pc  !=  delete_target -> pc_start ) {
821-                 block_t  * target  = 
822-                     cache_get (rv -> block_cache , untaken -> pc , false);
823-                 assert (target );
824-                 bool  flag  =  false;
825-                 list_for_each_entry_safe  (entry , safe , & target -> list , list ) {
826-                     if  (entry -> block  ==  delete_target ) {
827-                         list_del_init (& entry -> list );
828-                         mpool_free (rv -> chain_entry_mp , entry );
829-                         flag  =  true;
830-                     }
831-                 }
832-                 assert (flag );
833-             }
834-             /* correctly remove deleted block from the block chained to it */ 
835-             list_for_each_entry_safe  (entry , safe , & delete_target -> list , list ) {
836-                 if  (entry -> block  ==  delete_target )
837-                     continue ;
838-                 rv_insn_t  * target  =  entry -> block -> ir_tail ;
839-                 if  (target -> branch_taken  ==  delete_target -> ir_head )
840-                     target -> branch_taken  =  NULL ;
841-                 else  if  (target -> branch_untaken  ==  delete_target -> ir_head )
842-                     target -> branch_untaken  =  NULL ;
843-                 mpool_free (rv -> chain_entry_mp , entry );
844-             }
845-             /* free deleted block */ 
846-             uint32_t  idx ;
847-             rv_insn_t  * ir , * next ;
848-             for  (idx  =  0 , ir  =  delete_target -> ir_head ;
849-                  idx  <  delete_target -> n_insn ; idx ++ , ir  =  next ) {
850-                 free (ir -> fuse );
851-                 next  =  ir -> next ;
852-                 mpool_free (rv -> block_ir_mp , ir );
853-             }
854-             mpool_free (rv -> block_mp , delete_target );
833+     list_add (& next_blk -> list , & rv -> block_list );
834+ 
835+     /* insert the block into block cache */ 
836+     block_t  * replaced_blk  =  cache_put (rv -> block_cache , rv -> PC , & (* next_blk ));
837+ 
838+     if  (!replaced_blk )
839+         return  next_blk ;
840+ 
841+     list_del_init (& replaced_blk -> list );
842+ 
843+     if  (prev  ==  replaced_blk )
844+         prev  =  NULL ;
845+ 
846+     /* remove the connection from parents */ 
847+     rv_insn_t  * replaced_blk_entry  =  replaced_blk -> ir_head ;
848+ 
849+     /* TODO: record parents of each block to avoid traversing all blocks */ 
850+     block_t  * entry ;
851+     list_for_each_entry  (entry , & rv -> block_list , list ) {
852+         rv_insn_t  * taken  =  entry -> ir_tail -> branch_taken ,
853+                   * untaken  =  entry -> ir_tail -> branch_untaken ;
854+ 
855+         if  (taken  ==  replaced_blk_entry ) {
856+             entry -> ir_tail -> branch_taken  =  NULL ;
855857        }
856- #endif 
858+         if  (untaken  ==  replaced_blk_entry ) {
859+             entry -> ir_tail -> branch_untaken  =  NULL ;
860+         }
861+     }
862+ 
863+     /* free IRs in replaced block */ 
864+     for  (rv_insn_t  * ir  =  replaced_blk -> ir_head , * next_ir ; ir  !=  NULL ;
865+          ir  =  next_ir ) {
866+         next_ir  =  ir -> next ;
867+ 
868+         if  (ir -> fuse )
869+             free (ir -> fuse );
870+ 
871+         mpool_free (rv -> block_ir_mp , ir );
857872    }
858873
859-     return  next ;
874+     mpool_free (rv -> block_mp , replaced_blk );
875+ #endif 
876+ 
877+     assert (next_blk );
878+     return  next_blk ;
860879}
861880
862881#if  RV32_HAS (JIT )
@@ -918,31 +937,12 @@ void rv_step(void *arg)
918937            if  (!insn_is_unconditional_branch (last_ir -> opcode )) {
919938                if  (is_branch_taken  &&  !last_ir -> branch_taken ) {
920939                    last_ir -> branch_taken  =  block -> ir_head ;
921- #if  RV32_HAS (JIT )
922-                     chain_entry_t  * new_entry  =  mpool_alloc (rv -> chain_entry_mp );
923-                     new_entry -> block  =  prev ;
924-                     list_add (& new_entry -> list , & block -> list );
925- #endif 
926940                } else  if  (!is_branch_taken  &&  !last_ir -> branch_untaken ) {
927941                    last_ir -> branch_untaken  =  block -> ir_head ;
928- #if  RV32_HAS (JIT )
929-                     chain_entry_t  * new_entry  =  mpool_alloc (rv -> chain_entry_mp );
930-                     new_entry -> block  =  prev ;
931-                     list_add (& new_entry -> list , & block -> list );
932- #endif 
933942                }
934-             } else  if  (IF_insn (last_ir , jal )
935- #if  RV32_HAS (EXT_C )
936-                        ||  IF_insn (last_ir , cj ) ||  IF_insn (last_ir , cjal )
937- #endif 
938-             ) {
943+             } else  if  (insn_is_direct_branch (last_ir -> opcode )) {
939944                if  (!last_ir -> branch_taken ) {
940945                    last_ir -> branch_taken  =  block -> ir_head ;
941- #if  RV32_HAS (JIT )
942-                     chain_entry_t  * new_entry  =  mpool_alloc (rv -> chain_entry_mp );
943-                     new_entry -> block  =  prev ;
944-                     list_add (& new_entry -> list , & block -> list );
945- #endif 
946946                }
947947            }
948948        }
0 commit comments