diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c index 9d790b172c..858dfcc53a 100644 --- a/target/loongarch/disas.c +++ b/target/loongarch/disas.c @@ -352,6 +352,9 @@ INSN(bitrev_w, rr) INSN(bitrev_d, rr) INSN(ext_w_h, rr) INSN(ext_w_b, rr) +INSN(rdtimel_w, rr) +INSN(rdtimeh_w, rr) +INSN(rdtime_d, rr) INSN(cpucfg, rr) INSN(asrtle_d, rr_jk) INSN(asrtgt_d, rr_jk) diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 626fc32e1e..85c11a60d4 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -93,6 +93,8 @@ DEF_HELPER_2(frint_d, i64, env, i64) DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32) +DEF_HELPER_1(rdtime_d, i64, env) + /* CSRs helper */ DEF_HELPER_1(csrrd_pgd, i64, env) DEF_HELPER_1(csrrd_tval, i64, env) diff --git a/target/loongarch/insn_trans/trans_extra.c.inc b/target/loongarch/insn_trans/trans_extra.c.inc index 549f75a867..ad713cd61e 100644 --- a/target/loongarch/insn_trans/trans_extra.c.inc +++ b/target/loongarch/insn_trans/trans_extra.c.inc @@ -33,6 +33,39 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a) return true; } +static bool gen_rdtime(DisasContext *ctx, arg_rr *a, + bool word, bool high) +{ + TCGv dst1 = gpr_dst(ctx, a->rd, EXT_NONE); + TCGv dst2 = gpr_dst(ctx, a->rj, EXT_NONE); + + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + gen_helper_rdtime_d(dst1, cpu_env); + if (word) { + tcg_gen_sextract_tl(dst1, dst1, high ? 32 : 0, 32); + } + tcg_gen_ld_i64(dst2, cpu_env, offsetof(CPULoongArchState, CSR_TID)); + + return true; +} + +static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a) +{ + return gen_rdtime(ctx, a, 1, 0); +} + +static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a) +{ + return gen_rdtime(ctx, a, 1, 1); +} + +static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) +{ + return gen_rdtime(ctx, a, 0, 0); +} + static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a) { TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index ebd3d505fb..3fdc6e148c 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -309,6 +309,9 @@ break 0000 00000010 10100 ............... @i15 syscall 0000 00000010 10110 ............... @i15 asrtle_d 0000 00000000 00010 ..... ..... 00000 @rr_jk asrtgt_d 0000 00000000 00011 ..... ..... 00000 @rr_jk +rdtimel_w 0000 00000000 00000 11000 ..... ..... @rr +rdtimeh_w 0000 00000000 00000 11001 ..... ..... @rr +rdtime_d 0000 00000000 00000 11010 ..... ..... @rr cpucfg 0000 00000000 00000 11011 ..... ..... @rr # diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c index a9ba72d5b2..d87049851f 100644 --- a/target/loongarch/op_helper.c +++ b/target/loongarch/op_helper.c @@ -84,6 +84,19 @@ target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj) return rj > 21 ? 0 : env->cpucfg[rj]; } +uint64_t helper_rdtime_d(CPULoongArchState *env) +{ + uint64_t plv; + LoongArchCPU *cpu = env_archcpu(env); + + plv = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); + if (extract64(env->CSR_MISC, R_CSR_MISC_DRDTL_SHIFT + plv, 1)) { + do_raise_exception(env, EXCCODE_IPE, GETPC()); + } + + return cpu_loongarch_get_constant_timer_counter(cpu); +} + void helper_ertn(CPULoongArchState *env) { uint64_t csr_pplv, csr_pie; diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 0f098924a3..c9afd11420 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -25,6 +25,8 @@ static TCGv cpu_lladdr, cpu_llval; TCGv_i32 cpu_fcsr0; TCGv_i64 cpu_fpr[32]; +#include "exec/gen-icount.h" + #define DISAS_STOP DISAS_TARGET_0 #define DISAS_EXIT DISAS_TARGET_1 #define DISAS_EXIT_UPDATE DISAS_TARGET_2