@@ -180,6 +180,7 @@ struct DisasContext {
180180#if defined(TARGET_PPC64 )
181181 bool sf_mode ;
182182 bool has_cfar ;
183+ bool has_bhrb ;
183184#endif
184185 bool fpu_enabled ;
185186 bool altivec_enabled ;
@@ -3371,14 +3372,85 @@ static void gen_rvwinkle(DisasContext *ctx)
33713372 gen_exception_nip (ctx , EXCP_HLT , ctx -> base .pc_next );
33723373#endif /* defined(CONFIG_USER_ONLY) */
33733374}
3375+
3376+ static inline TCGv gen_write_bhrb (TCGv_ptr base , TCGv offset , TCGv mask , TCGv value )
3377+ {
3378+ TCGv_ptr tmp = tcg_temp_new_ptr ();
3379+
3380+ /* add base and offset to get address of bhrb entry */
3381+ tcg_gen_add_ptr (tmp , base , (TCGv_ptr )offset );
3382+
3383+ /* store value into bhrb at bhrb_offset */
3384+ tcg_gen_st_i64 (value , tmp , 0 );
3385+
3386+ /* add 8 to current bhrb_offset */
3387+ tcg_gen_addi_tl (offset , offset , 8 );
3388+
3389+ /* apply offset mask */
3390+ tcg_gen_and_tl (offset , offset , mask );
3391+
3392+ return offset ;
3393+ }
33743394#endif /* #if defined(TARGET_PPC64) */
33753395
3376- static inline void gen_update_cfar (DisasContext * ctx , target_ulong nip )
3396+ static inline void gen_update_branch_history (DisasContext * ctx ,
3397+ target_ulong nip ,
3398+ TCGv target ,
3399+ target_long inst_type )
33773400{
33783401#if defined(TARGET_PPC64 )
3402+ TCGv_ptr base ;
3403+ TCGv tmp ;
3404+ TCGv offset ;
3405+ TCGv mask ;
3406+ TCGLabel * no_update ;
3407+
33793408 if (ctx -> has_cfar ) {
33803409 tcg_gen_movi_tl (cpu_cfar , nip );
33813410 }
3411+
3412+ if (!ctx -> has_bhrb ||
3413+ !ctx -> bhrb_enable ||
3414+ inst_type == BHRB_TYPE_NORECORD ) {
3415+ return ;
3416+ }
3417+
3418+ tmp = tcg_temp_new ();
3419+ no_update = gen_new_label ();
3420+
3421+ /* check for bhrb filtering */
3422+ tcg_gen_ld_tl (tmp , tcg_env , offsetof(CPUPPCState , bhrb_filter ));
3423+ tcg_gen_andi_tl (tmp , tmp , inst_type );
3424+ tcg_gen_brcondi_tl (TCG_COND_EQ , tmp , 0 , no_update );
3425+
3426+ base = tcg_temp_new_ptr ();
3427+ offset = tcg_temp_new ();
3428+ mask = tcg_temp_new ();
3429+
3430+ /* load bhrb base address */
3431+ tcg_gen_ld_ptr (base , tcg_env , offsetof(CPUPPCState , bhrb_base ));
3432+
3433+ /* load current bhrb_offset */
3434+ tcg_gen_ld_tl (offset , tcg_env , offsetof(CPUPPCState , bhrb_offset ));
3435+
3436+ /* load a BHRB offset mask */
3437+ tcg_gen_ld_tl (mask , tcg_env , offsetof(CPUPPCState , bhrb_offset_mask ));
3438+
3439+ offset = gen_write_bhrb (base , offset , mask , tcg_constant_i64 (nip ));
3440+
3441+ /* Also record the target address for XL-Form branches */
3442+ if (inst_type & BHRB_TYPE_XL_FORM ) {
3443+
3444+ /* Set the 'T' bit for target entries */
3445+ tcg_gen_ori_tl (tmp , target , 0x2 );
3446+
3447+ offset = gen_write_bhrb (base , offset , mask , tmp );
3448+ }
3449+
3450+ /* save updated bhrb_offset for next time */
3451+ tcg_gen_st_tl (offset , tcg_env , offsetof(CPUPPCState , bhrb_offset ));
3452+
3453+ gen_set_label (no_update );
33823454#endif
33833455}
33843456
@@ -3508,8 +3580,10 @@ static void gen_b(DisasContext *ctx)
35083580 }
35093581 if (LK (ctx -> opcode )) {
35103582 gen_setlr (ctx , ctx -> base .pc_next );
3583+ gen_update_branch_history (ctx , ctx -> cia , NULL , BHRB_TYPE_CALL );
3584+ } else {
3585+ gen_update_branch_history (ctx , ctx -> cia , NULL , BHRB_TYPE_OTHER );
35113586 }
3512- gen_update_cfar (ctx , ctx -> cia );
35133587 gen_goto_tb (ctx , 0 , target );
35143588 ctx -> base .is_jmp = DISAS_NORETURN ;
35153589}
@@ -3524,6 +3598,7 @@ static void gen_bcond(DisasContext *ctx, int type)
35243598 uint32_t bo = BO (ctx -> opcode );
35253599 TCGLabel * l1 ;
35263600 TCGv target ;
3601+ target_long bhrb_type = BHRB_TYPE_OTHER ;
35273602
35283603 if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR ) {
35293604 target = tcg_temp_new ();
@@ -3534,11 +3609,16 @@ static void gen_bcond(DisasContext *ctx, int type)
35343609 } else {
35353610 tcg_gen_mov_tl (target , cpu_lr );
35363611 }
3612+ if (!LK (ctx -> opcode )) {
3613+ bhrb_type |= BHRB_TYPE_INDIRECT ;
3614+ }
3615+ bhrb_type |= BHRB_TYPE_XL_FORM ;
35373616 } else {
35383617 target = NULL ;
35393618 }
35403619 if (LK (ctx -> opcode )) {
35413620 gen_setlr (ctx , ctx -> base .pc_next );
3621+ bhrb_type |= BHRB_TYPE_CALL ;
35423622 }
35433623 l1 = gen_new_label ();
35443624 if ((bo & 0x4 ) == 0 ) {
@@ -3589,6 +3669,7 @@ static void gen_bcond(DisasContext *ctx, int type)
35893669 tcg_gen_brcondi_tl (TCG_COND_EQ , temp , 0 , l1 );
35903670 }
35913671 }
3672+ bhrb_type |= BHRB_TYPE_COND ;
35923673 }
35933674 if ((bo & 0x10 ) == 0 ) {
35943675 /* Test CR */
@@ -3603,8 +3684,11 @@ static void gen_bcond(DisasContext *ctx, int type)
36033684 tcg_gen_andi_i32 (temp , cpu_crf [bi >> 2 ], mask );
36043685 tcg_gen_brcondi_i32 (TCG_COND_NE , temp , 0 , l1 );
36053686 }
3687+ bhrb_type |= BHRB_TYPE_COND ;
36063688 }
3607- gen_update_cfar (ctx , ctx -> cia );
3689+
3690+ gen_update_branch_history (ctx , ctx -> cia , target , bhrb_type );
3691+
36083692 if (type == BCOND_IM ) {
36093693 target_ulong li = (target_long )((int16_t )(BD (ctx -> opcode )));
36103694 if (likely (AA (ctx -> opcode ) == 0 )) {
@@ -3720,7 +3804,7 @@ static void gen_rfi(DisasContext *ctx)
37203804 /* Restore CPU state */
37213805 CHK_SV (ctx );
37223806 translator_io_start (& ctx -> base );
3723- gen_update_cfar (ctx , ctx -> cia );
3807+ gen_update_branch_history (ctx , ctx -> cia , NULL , BHRB_TYPE_NORECORD );
37243808 gen_helper_rfi (tcg_env );
37253809 ctx -> base .is_jmp = DISAS_EXIT ;
37263810#endif
@@ -3735,7 +3819,7 @@ static void gen_rfid(DisasContext *ctx)
37353819 /* Restore CPU state */
37363820 CHK_SV (ctx );
37373821 translator_io_start (& ctx -> base );
3738- gen_update_cfar (ctx , ctx -> cia );
3822+ gen_update_branch_history (ctx , ctx -> cia , NULL , BHRB_TYPE_NORECORD );
37393823 gen_helper_rfid (tcg_env );
37403824 ctx -> base .is_jmp = DISAS_EXIT ;
37413825#endif
@@ -3750,7 +3834,7 @@ static void gen_rfscv(DisasContext *ctx)
37503834 /* Restore CPU state */
37513835 CHK_SV (ctx );
37523836 translator_io_start (& ctx -> base );
3753- gen_update_cfar (ctx , ctx -> cia );
3837+ gen_update_branch_history (ctx , ctx -> cia , NULL , BHRB_TYPE_NORECORD );
37543838 gen_helper_rfscv (tcg_env );
37553839 ctx -> base .is_jmp = DISAS_EXIT ;
37563840#endif
@@ -6330,6 +6414,7 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
63306414#if defined(TARGET_PPC64 )
63316415 ctx -> sf_mode = (hflags >> HFLAGS_64 ) & 1 ;
63326416 ctx -> has_cfar = !!(env -> flags & POWERPC_FLAG_CFAR );
6417+ ctx -> has_bhrb = !!(env -> flags & POWERPC_FLAG_BHRB );
63336418#endif
63346419 ctx -> lazy_tlb_flush = env -> mmu_model == POWERPC_MMU_32B
63356420 || env -> mmu_model & POWERPC_MMU_64 ;
0 commit comments