@@ -455,6 +455,7 @@ struct ArchCPU {
uint32_t pmu_avail_ctrs;
/* Mapping of events to counters */
GHashTable *pmu_event_ctr_map;
+ const GPtrArray *decoders;
};
/**
@@ -26,4 +26,19 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp);
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu);
+struct DisasContext;
+struct RISCVCPUConfig;
+typedef struct RISCVDecoder {
+ bool (*guard_func)(const struct RISCVCPUConfig *);
+ bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
+} RISCVDecoder;
+
+typedef bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
+
+extern const size_t decoder_table_size;
+
+extern const RISCVDecoder decoder_table[];
+
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu);
+
#endif
@@ -1134,6 +1134,7 @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
error_propagate(errp, local_err);
return;
}
+ riscv_tcg_cpu_finalize_dynamic_decoder(cpu);
} else if (kvm_enabled()) {
riscv_kvm_cpu_finalize_features(cpu, &local_err);
if (local_err != NULL) {
@@ -863,6 +863,21 @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
}
}
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu)
+{
+ GPtrArray *dynamic_decoders;
+ dynamic_decoders = g_ptr_array_sized_new(decoder_table_size);
+ for (size_t i = 0; i < decoder_table_size; ++i) {
+ if (decoder_table[i].guard_func &&
+ decoder_table[i].guard_func(&cpu->cfg)) {
+ g_ptr_array_add(dynamic_decoders,
+ (gpointer)decoder_table[i].riscv_cpu_decode_fn);
+ }
+ }
+
+ cpu->decoders = dynamic_decoders;
+}
+
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu)
{
return object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST) == NULL;
@@ -35,6 +35,8 @@
#include "exec/helper-info.c.inc"
#undef HELPER_H
+#include "tcg/tcg-cpu.h"
+
/* global register indices */
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
@@ -114,6 +116,7 @@ typedef struct DisasContext {
/* FRM is known to contain a valid value. */
bool frm_valid;
bool insn_start_updated;
+ const GPtrArray *decoders;
} DisasContext;
static inline bool has_ext(DisasContext *ctx, uint32_t ext)
@@ -1123,21 +1126,16 @@ static inline int insn_len(uint16_t first_word)
return (first_word & 3) == 3 ? 4 : 2;
}
+const RISCVDecoder decoder_table[] = {
+ { always_true_p, decode_insn32 },
+ { has_xthead_p, decode_xthead},
+ { has_XVentanaCondOps_p, decode_XVentanaCodeOps},
+};
+
+const size_t decoder_table_size = ARRAY_SIZE(decoder_table);
+
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
{
- /*
- * A table with predicate (i.e., guard) functions and decoder functions
- * that are tested in-order until a decoder matches onto the opcode.
- */
- static const struct {
- bool (*guard_func)(const RISCVCPUConfig *);
- bool (*decode_func)(DisasContext *, uint32_t);
- } decoders[] = {
- { always_true_p, decode_insn32 },
- { has_xthead_p, decode_xthead },
- { has_XVentanaCondOps_p, decode_XVentanaCodeOps },
- };
-
ctx->virt_inst_excp = false;
ctx->cur_insn_len = insn_len(opcode);
/* Check for compressed insn */
@@ -1158,9 +1156,9 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
ctx->base.pc_next + 2));
ctx->opcode = opcode32;
- for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
- if (decoders[i].guard_func(ctx->cfg_ptr) &&
- decoders[i].decode_func(ctx, opcode32)) {
+ for (guint i = 0; i < ctx->decoders->len; ++i) {
+ riscv_cpu_decode_fn func = g_ptr_array_index(ctx->decoders, i);
+ if (func(ctx, opcode32)) {
return;
}
}
@@ -1205,6 +1203,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
ctx->zero = tcg_constant_tl(0);
ctx->virt_inst_excp = false;
+ ctx->decoders = cpu->decoders;
}
static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)