Commit b00c7218 authored by Yongbok Kim's avatar Yongbok Kim Committed by Leon Alrae
Browse files

target-mips: add PC, XNP reg numbers to RDHWR



Add Performance Counter (4) and XNP (5) register numbers to RDHWR.
Add check_hwrena() to simplify access control checkings.
Add RDHWR support to microMIPS R6.

Signed-off-by: default avatarYongbok Kim <yongbok.kim@imgtec.com>
Reviewed-by: default avatarLeon Alrae <leon.alrae@imgtec.com>
Signed-off-by: default avatarLeon Alrae <leon.alrae@imgtec.com>
parent ca2f6bbb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -469,6 +469,7 @@ struct CPUMIPSState {
#define CP0C5_CV         29
#define CP0C5_EVA        28
#define CP0C5_MSAEn      27
#define CP0C5_XNP        13
#define CP0C5_UFE        9
#define CP0C5_FRE        8
#define CP0C5_SBRI       6
+2 −0
Original line number Diff line number Diff line
@@ -358,6 +358,8 @@ DEF_HELPER_1(rdhwr_cpunum, tl, env)
DEF_HELPER_1(rdhwr_synci_step, tl, env)
DEF_HELPER_1(rdhwr_cc, tl, env)
DEF_HELPER_1(rdhwr_ccres, tl, env)
DEF_HELPER_1(rdhwr_performance, tl, env)
DEF_HELPER_1(rdhwr_xnp, tl, env)
DEF_HELPER_2(pmon, void, env, int)
DEF_HELPER_1(wait, void, env)

+35 −29
Original line number Diff line number Diff line
@@ -1357,6 +1357,13 @@ void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
{
    uint32_t mask = 0x0000000F;

    if ((env->CP0_Config1 & (1 << CP0C1_PC)) &&
        (env->insn_flags & ISA_MIPS32R6)) {
        mask |= (1 << 4);
    }
    if (env->insn_flags & ISA_MIPS32R6) {
        mask |= (1 << 5);
    }
    if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
        mask |= (1 << 29);

@@ -2185,53 +2192,52 @@ void helper_deret(CPUMIPSState *env)
}
#endif /* !CONFIG_USER_ONLY */

target_ulong helper_rdhwr_cpunum(CPUMIPSState *env)
static inline void check_hwrena(CPUMIPSState *env, int reg)
{
    if ((env->hflags & MIPS_HFLAG_CP0) ||
        (env->CP0_HWREna & (1 << 0)))
        return env->CP0_EBase & 0x3ff;
    else
    if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) {
        return;
    }
    do_raise_exception(env, EXCP_RI, GETPC());
}

    return 0;
target_ulong helper_rdhwr_cpunum(CPUMIPSState *env)
{
    check_hwrena(env, 0);
    return env->CP0_EBase & 0x3ff;
}

target_ulong helper_rdhwr_synci_step(CPUMIPSState *env)
{
    if ((env->hflags & MIPS_HFLAG_CP0) ||
        (env->CP0_HWREna & (1 << 1)))
    check_hwrena(env, 1);
    return env->SYNCI_Step;
    else
        do_raise_exception(env, EXCP_RI, GETPC());

    return 0;
}

target_ulong helper_rdhwr_cc(CPUMIPSState *env)
{
    if ((env->hflags & MIPS_HFLAG_CP0) ||
        (env->CP0_HWREna & (1 << 2))) {
    check_hwrena(env, 2);
#ifdef CONFIG_USER_ONLY
    return env->CP0_Count;
#else
    return (int32_t)cpu_mips_get_count(env);
#endif
    } else {
        do_raise_exception(env, EXCP_RI, GETPC());
    }

    return 0;
}

target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
{
    if ((env->hflags & MIPS_HFLAG_CP0) ||
        (env->CP0_HWREna & (1 << 3)))
    check_hwrena(env, 3);
    return env->CCRes;
    else
        do_raise_exception(env, EXCP_RI, GETPC());
}

    return 0;
target_ulong helper_rdhwr_performance(CPUMIPSState *env)
{
    check_hwrena(env, 4);
    return env->CP0_Performance0;
}

target_ulong helper_rdhwr_xnp(CPUMIPSState *env)
{
    check_hwrena(env, 5);
    return (env->CP0_Config5 >> CP0C5_XNP) & 1;
}

void helper_pmon(CPUMIPSState *env, int function)
+25 −3
Original line number Diff line number Diff line
@@ -10333,7 +10333,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
    }
}
static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
{
    TCGv t0;
@@ -10361,6 +10361,22 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
        gen_helper_rdhwr_ccres(t0, cpu_env);
        gen_store_gpr(t0, rt);
        break;
    case 4:
        check_insn(ctx, ISA_MIPS32R6);
        if (sel != 0) {
            /* Performance counter registers are not implemented other than
             * control register 0.
             */
            generate_exception(ctx, EXCP_RI);
        }
        gen_helper_rdhwr_performance(t0, cpu_env);
        gen_store_gpr(t0, rt);
        break;
    case 5:
        check_insn(ctx, ISA_MIPS32R6);
        gen_helper_rdhwr_xnp(t0, cpu_env);
        gen_store_gpr(t0, rt);
        break;
    case 29:
#if defined(CONFIG_USER_ONLY)
        tcg_gen_ld_tl(t0, cpu_env,
@@ -11979,6 +11995,7 @@ enum {
    ROTR = 0x3,
    SELEQZ = 0x5,
    SELNEZ = 0x6,
    R6_RDHWR = 0x7,
    SLLV = 0x0,
    SRLV = 0x1,
@@ -12932,7 +12949,8 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
            gen_cl(ctx, mips32_op, rt, rs);
            break;
        case RDHWR:
            gen_rdhwr(ctx, rt, rs);
            check_insn_opc_removed(ctx, ISA_MIPS32R6);
            gen_rdhwr(ctx, rt, rs, 0);
            break;
        case WSBH:
            gen_bshfl(ctx, OPC_WSBH, rs, rt);
@@ -13487,6 +13505,10 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
                check_insn(ctx, ISA_MIPS32R6);
                gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
                break;
            case R6_RDHWR:
                check_insn(ctx, ISA_MIPS32R6);
                gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
                break;
            default:
                goto pool32a_invalid;
            }
@@ -17733,7 +17755,7 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
        break;
#endif
    case OPC_RDHWR:
        gen_rdhwr(ctx, rt, rd);
        gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
        break;
    case OPC_FORK:
        check_insn(ctx, ASE_MT);