@@ -533,8 +533,40 @@ 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;
536538 }
537- return false;
539+ __UNREACHABLE ;
540+ }
541+
542+ FORCE_INLINE bool insn_is_direct_branch (uint8_t opcode )
543+ {
544+ switch (opcode ) {
545+ case rv_insn_jal :
546+ #if RV32_HAS (EXT_C )
547+ case rv_insn_cjal :
548+ case rv_insn_cj :
549+ #endif
550+ return true;
551+ default :
552+ return false;
553+ }
554+ __UNREACHABLE ;
555+ }
556+
557+ FORCE_INLINE bool insn_is_indirect_branch (uint8_t opcode )
558+ {
559+ switch (opcode ) {
560+ case rv_insn_jalr :
561+ #if RV32_HAS (EXT_C )
562+ case rv_insn_cjalr :
563+ case rv_insn_cjr :
564+ #endif
565+ return true;
566+ default :
567+ return false;
568+ }
569+ __UNREACHABLE ;
538570}
539571
540572static void block_translate (riscv_t * rv , block_t * block )
@@ -571,11 +603,7 @@ static void block_translate(riscv_t *rv, block_t *block)
571603#endif
572604 /* stop on branch */
573605 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- ) {
606+ if (insn_is_indirect_branch (ir -> opcode )) {
579607 ir -> branch_table = calloc (1 , sizeof (branch_history_table_t ));
580608 assert (ir -> branch_table );
581609 memset (ir -> branch_table -> PC , -1 ,
@@ -768,95 +796,89 @@ static block_t *block_find_or_translate(riscv_t *rv)
768796#if !RV32_HAS (JIT )
769797 block_map_t * map = & rv -> block_map ;
770798 /* lookup the next block in the block map */
771- block_t * next = block_find (map , rv -> PC );
799+ block_t * next_blk = block_find (map , rv -> PC );
772800#else
773801 /* lookup the next block in the block cache */
774- block_t * next = (block_t * ) cache_get (rv -> block_cache , rv -> PC , true);
802+ /*
803+ * The function "cache_get()" gets the cached block by the given "key (PC)".
804+ * In system simulation, the returned block might be dropped because it is
805+ * not the one from the current process (by checking SATP CSR register).
806+ */
807+ block_t * next_blk = (block_t * ) cache_get (rv -> block_cache , rv -> PC , true);
775808#endif
776809
777- if (!next ) {
810+ if (next_blk )
811+ return next_blk ;
812+
778813#if !RV32_HAS (JIT )
779- if (map -> size * 1.25 > map -> block_capacity ) {
780- block_map_clear (rv );
781- prev = NULL ;
782- }
814+ /* clear block list if it is going to be filled */
815+ if (map -> size * 1.25 > map -> block_capacity ) {
816+ block_map_clear (rv );
817+ prev = NULL ;
818+ }
783819#endif
784- /* allocate a new block */
785- next = block_alloc (rv );
786- block_translate (rv , next );
820+ /* allocate a new block */
821+ next_blk = block_alloc (rv );
822+
823+ block_translate (rv , next_blk );
787824
788- optimize_constant (rv , next );
825+ optimize_constant (rv , next_blk );
789826#if RV32_HAS (GDBSTUB )
790- if (likely (!rv -> debug_mode ))
827+ if (likely (!rv -> debug_mode ))
791828#endif
792- /* macro operation fusion */
793- match_pattern (rv , next );
829+ /* macro operation fusion */
830+ match_pattern (rv , next_blk );
794831
795832#if !RV32_HAS (JIT )
796- /* insert the block into block map */
797- block_insert (& rv -> block_map , next );
833+ /* insert the block into block map */
834+ block_insert (& rv -> block_map , next_blk );
798835#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 );
836+ list_add (& next_blk -> list , & rv -> block_list );
837+
838+ /* insert the block into block cache */
839+ block_t * replaced_blk = cache_put (rv -> block_cache , rv -> PC , & (* next_blk ));
840+
841+ if (!replaced_blk )
842+ return next_blk ;
843+
844+ list_del_init (& replaced_blk -> list );
845+
846+ if (prev == replaced_blk )
847+ prev = NULL ;
848+
849+ /* remove the connection from parents */
850+ rv_insn_t * replaced_blk_entry = replaced_blk -> ir_head ;
851+
852+ /* TODO: record parents of each block to avoid traversing all blocks */
853+ block_t * entry ;
854+ list_for_each_entry (entry , & rv -> block_list , list ) {
855+ rv_insn_t * taken = entry -> ir_tail -> branch_taken ,
856+ * untaken = entry -> ir_tail -> branch_untaken ;
857+
858+ if (taken == replaced_blk_entry ) {
859+ entry -> ir_tail -> branch_taken = NULL ;
855860 }
856- #endif
861+ if (untaken == replaced_blk_entry ) {
862+ entry -> ir_tail -> branch_untaken = NULL ;
863+ }
864+ }
865+
866+ /* free IRs in replaced block */
867+ for (rv_insn_t * ir = replaced_blk -> ir_head , * next_ir ; ir != NULL ;
868+ ir = next_ir ) {
869+ next_ir = ir -> next ;
870+
871+ if (ir -> fuse )
872+ free (ir -> fuse );
873+
874+ mpool_free (rv -> block_ir_mp , ir );
857875 }
858876
859- return next ;
877+ mpool_free (rv -> block_mp , replaced_blk );
878+ #endif
879+
880+ assert (next_blk );
881+ return next_blk ;
860882}
861883
862884#if RV32_HAS (JIT )
@@ -918,31 +940,12 @@ void rv_step(void *arg)
918940 if (!insn_is_unconditional_branch (last_ir -> opcode )) {
919941 if (is_branch_taken && !last_ir -> branch_taken ) {
920942 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
926943 } else if (!is_branch_taken && !last_ir -> branch_untaken ) {
927944 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
933945 }
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- ) {
946+ } else if (insn_is_direct_branch (last_ir -> opcode )) {
939947 if (!last_ir -> branch_taken ) {
940948 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
946949 }
947950 }
948951 }
0 commit comments