diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 2f91d7dc33..c358927211 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -535,6 +535,7 @@ FIELD(MSR, LE, MSR_LE, 1) #define MMCR0_PMCjCE PPC_BIT(49) /* MMCR0 PMCj Condition Enabled */ #define MMCR0_FCP PPC_BIT(34) /* Freeze Counters/BHRB if PR=1 */ #define MMCR0_FCPC PPC_BIT(51) /* Condition for FCP bit */ +#define MMCR0_BHRBA_NR PPC_BIT_NR(42) /* BHRB Available */ /* MMCR0 userspace r/w mask */ #define MMCR0_UREG_MASK (MMCR0_FC | MMCR0_PMAO | MMCR0_PMAE) /* MMCR2 userspace r/w mask */ @@ -634,6 +635,7 @@ FIELD(MSR, LE, MSR_LE, 1) /* HFSCR bits */ #define HFSCR_MSGP PPC_BIT(53) /* Privileged Message Send Facilities */ +#define HFSCR_BHRB PPC_BIT(59) /* BHRB Instructions */ #define HFSCR_IC_MSGP 0xA #define DBCR0_ICMP (1 << 27) diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 7b07cd1a49..55293e20a9 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -820,3 +820,10 @@ DEF_HELPER_4(DSCLIQ, void, env, fprp, fprp, i32) DEF_HELPER_1(tbegin, void, env) DEF_HELPER_FLAGS_1(fixup_thrm, TCG_CALL_NO_RWG, void, env) + +#if !defined(CONFIG_USER_ONLY) +#if defined(TARGET_PPC64) +DEF_HELPER_1(clrbhrb, void, env) +DEF_HELPER_FLAGS_2(mfbhrbe, TCG_CALL_NO_WG, i64, env, i32) +#endif +#endif diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode index 05c1d8c12d..d4dd022df4 100644 --- a/target/ppc/insn32.decode +++ b/target/ppc/insn32.decode @@ -1190,3 +1190,11 @@ MSGSYNC 011111 ----- ----- ----- 1101110110 - @X_sync ...... .. l:3 ... sc:2 ..... .......... . &X_sync SYNC 011111 -- ... --- .. ----- 1001010110 - @X_sync EIEIO 011111 ----- ----- ----- 1101010110 - + +# Branch History Rolling Buffer (BHRB) Instructions + +&XFX_bhrbe rt bhrbe +@XFX_bhrbe ...... rt:5 bhrbe:10 .......... - &XFX_bhrbe + +MFBHRBE 011111 ..... ..... ..... 0100101110 - @XFX_bhrbe +CLRBHRB 011111 ----- ----- ----- 0110101110 - diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index 58e808dc96..6f419c9346 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -150,6 +150,17 @@ void helper_msr_facility_check(CPUPPCState *env, uint32_t bit, #if !defined(CONFIG_USER_ONLY) +#ifdef TARGET_PPC64 +static void helper_mmcr0_facility_check(CPUPPCState *env, uint32_t bit, + uint32_t sprn, uint32_t cause) +{ + if (FIELD_EX64(env->msr, MSR, PR) && + !(env->spr[SPR_POWER_MMCR0] & (1ULL << bit))) { + raise_fu_exception(env, bit, sprn, cause, GETPC()); + } +} +#endif + void helper_store_sdr1(CPUPPCState *env, target_ulong val) { if (env->spr[SPR_SDR1] != val) { @@ -363,3 +374,42 @@ void helper_fixup_thrm(CPUPPCState *env) env->spr[i] = v; } } + +#if !defined(CONFIG_USER_ONLY) +#if defined(TARGET_PPC64) +void helper_clrbhrb(CPUPPCState *env) +{ + helper_hfscr_facility_check(env, HFSCR_BHRB, "clrbhrb", FSCR_IC_BHRB); + + helper_mmcr0_facility_check(env, MMCR0_BHRBA_NR, 0, FSCR_IC_BHRB); + + if (env->flags & POWERPC_FLAG_BHRB) { + memset(env->bhrb, 0, sizeof(env->bhrb)); + } +} + +uint64_t helper_mfbhrbe(CPUPPCState *env, uint32_t bhrbe) +{ + unsigned int index; + + helper_hfscr_facility_check(env, HFSCR_BHRB, "mfbhrbe", FSCR_IC_BHRB); + + helper_mmcr0_facility_check(env, MMCR0_BHRBA_NR, 0, FSCR_IC_BHRB); + + if (!(env->flags & POWERPC_FLAG_BHRB) || + (bhrbe >= env->bhrb_num_entries) || + (env->spr[SPR_POWER_MMCR0] & MMCR0_PMAE)) { + return 0; + } + + /* + * Note: bhrb_offset is the byte offset for writing the + * next entry (over the oldest entry), which is why we + * must offset bhrbe by 1 to get to the 0th entry. + */ + index = ((env->bhrb_offset / sizeof(uint64_t)) - (bhrbe + 1)) % + env->bhrb_num_entries; + return env->bhrb[index]; +} +#endif +#endif diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 8aa2439700..546f1754de 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -5647,6 +5647,8 @@ static bool resolve_PLS_D(DisasContext *ctx, arg_D *d, arg_PLS_D *a) #include "translate/misc-impl.c.inc" +#include "translate/bhrb-impl.c.inc" + /* Handles lfdp */ static void gen_dform39(DisasContext *ctx) { diff --git a/target/ppc/translate/bhrb-impl.c.inc b/target/ppc/translate/bhrb-impl.c.inc new file mode 100644 index 0000000000..3a19bc4555 --- /dev/null +++ b/target/ppc/translate/bhrb-impl.c.inc @@ -0,0 +1,43 @@ +/* + * Power ISA Decode For BHRB Instructions + * + * Copyright IBM Corp. 2023 + * + * Authors: + * Glenn Miles <milesg@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) + +static bool trans_MFBHRBE(DisasContext *ctx, arg_XFX_bhrbe *arg) +{ + REQUIRE_INSNS_FLAGS2(ctx, ISA207S); + TCGv_i32 bhrbe = tcg_constant_i32(arg->bhrbe); + gen_helper_mfbhrbe(cpu_gpr[arg->rt], tcg_env, bhrbe); + return true; +} + +static bool trans_CLRBHRB(DisasContext *ctx, arg_CLRBHRB *arg) +{ + REQUIRE_INSNS_FLAGS2(ctx, ISA207S); + gen_helper_clrbhrb(tcg_env); + return true; +} + +#else + +static bool trans_MFBHRBE(DisasContext *ctx, arg_XFX_bhrbe *arg) +{ + gen_invalid(ctx); + return true; +} + +static bool trans_CLRBHRB(DisasContext *ctx, arg_CLRBHRB *arg) +{ + gen_invalid(ctx); + return true; +} +#endif