@@ -533,8 +533,40 @@ FORCE_INLINE bool insn_is_unconditional_branch(uint8_t opcode)
533
533
case rv_insn_cebreak :
534
534
#endif
535
535
return true;
536
+ default :
537
+ return false;
536
538
}
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 ;
538
570
}
539
571
540
572
static void block_translate (riscv_t * rv , block_t * block )
@@ -571,11 +603,7 @@ static void block_translate(riscv_t *rv, block_t *block)
571
603
#endif
572
604
/* stop on branch */
573
605
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 )) {
579
607
ir -> branch_table = calloc (1 , sizeof (branch_history_table_t ));
580
608
assert (ir -> branch_table );
581
609
memset (ir -> branch_table -> PC , -1 ,
@@ -768,95 +796,89 @@ static block_t *block_find_or_translate(riscv_t *rv)
768
796
#if !RV32_HAS (JIT )
769
797
block_map_t * map = & rv -> block_map ;
770
798
/* 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 );
772
800
#else
773
801
/* 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);
775
808
#endif
776
809
777
- if (!next ) {
810
+ if (next_blk )
811
+ return next_blk ;
812
+
778
813
#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
+ }
783
819
#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 );
787
824
788
- optimize_constant (rv , next );
825
+ optimize_constant (rv , next_blk );
789
826
#if RV32_HAS (GDBSTUB )
790
- if (likely (!rv -> debug_mode ))
827
+ if (likely (!rv -> debug_mode ))
791
828
#endif
792
- /* macro operation fusion */
793
- match_pattern (rv , next );
829
+ /* macro operation fusion */
830
+ match_pattern (rv , next_blk );
794
831
795
832
#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 );
798
835
#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 ;
855
860
}
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 );
857
875
}
858
876
859
- return next ;
877
+ mpool_free (rv -> block_mp , replaced_blk );
878
+ #endif
879
+
880
+ assert (next_blk );
881
+ return next_blk ;
860
882
}
861
883
862
884
#if RV32_HAS (JIT )
@@ -918,31 +940,12 @@ void rv_step(void *arg)
918
940
if (!insn_is_unconditional_branch (last_ir -> opcode )) {
919
941
if (is_branch_taken && !last_ir -> branch_taken ) {
920
942
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
926
943
} else if (!is_branch_taken && !last_ir -> branch_untaken ) {
927
944
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
933
945
}
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 )) {
939
947
if (!last_ir -> branch_taken ) {
940
948
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
946
949
}
947
950
}
948
951
}
0 commit comments