This is inspired by Antmicro's work on their fork of TCG. We try to decode custom instrucions first - - if the decoders reject what they encounter, invoke the decoders for standard instructions.
Caveats: the pc_succ_next shall be corrected if custom decoder rejcets the incoming opcode. Signed-off-by: Ruinland Chuan-Tzu Tsai <ruinl...@andestech.com> --- target/riscv/cpu.c | 25 ++++++++++--- target/riscv/translate.c | 78 ++++++++++++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 18 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index fe63e68b8e..e8ab5734c2 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -36,6 +36,14 @@ static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG"; GHashTable *custom_csr_map = NULL; #include "custom_csr_defs.h" +#include "custom_insn_defs.h" + +/* Custom instruction related prototypes/variables */ +bool (*custom_c_insn_handler) (DisasContext *, uint16_t); +bool (*custom_insn_handler) (DisasContext *, uint32_t); +__thread bool cpu_has_custom_insns = false; +/* Custom instruction handlers sometimes needs hart state */ +__thread CPURISCVState *HartState = NULL; const char * const riscv_int_regnames[] = { "x0/zero", "x1/ra", "x2/sp", "x3/gp", "x4/tp", "x5/t0", "x6/t1", @@ -151,12 +159,20 @@ static void set_resetvec(CPURISCVState *env, target_ulong resetvec) env->resetvec = resetvec; #endif } +void setup_custom_csr(CPURISCVState *env, + riscv_custom_csr_operations csr_map_struct[] + ); + +void setup_custom_csr(CPURISCVState *env, + riscv_custom_csr_operations csr_map_struct[] + ) { + + env->custom_csr_map = g_hash_table_new_full(g_direct_hash, \ + g_direct_equal, \ + NULL, NULL); + -static void setup_custom_csr(CPURISCVState *env, - riscv_custom_csr_operations csr_map_struct[]) -{ int i; - env->custom_csr_map = g_hash_table_new(g_direct_hash, g_direct_equal); for (i = 0; i < MAX_CUSTOM_CSR_NUM; i++) { if (csr_map_struct[i].csrno != 0) { g_hash_table_insert(env->custom_csr_map, @@ -187,6 +203,7 @@ static void rv64_base_cpu_init(Object *obj) set_misa(env, RV64); } + static void ax25_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 74b33fa3c9..f755749380 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -485,27 +485,77 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) /* Include the auto-generated decoder for 16 bit insn */ #include "decode-insn16.c.inc" -static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode) +/* Custom insn related definitions/prototypes */ +extern __thread bool cpu_has_custom_insns; +/* + * These 2 are for indication if decode fails. + * We don't want to interfere the following regular extension decoding + * We assume MTTCG is 1-1 mapping for now. + */ +__thread bool custom_c_insn_decoded; +__thread bool custom_insn_decoded; + +extern bool (*custom_c_insn_handler)(DisasContext *, uint16_t); +extern bool (*custom_insn_handler)(DisasContext *, uint32_t); + +static void try_decode_custom_insn(CPURISCVState *env, DisasContext *ctx, + uint16_t opcode) { - /* check for compressed insn */ - if (extract16(opcode, 0, 2) != 3) { + bool is_compressed_custom = false; + is_compressed_custom = extract16(opcode, 0, 2) != 3 ? true : false; + if (is_compressed_custom) { if (!has_ext(ctx, RVC)) { gen_exception_illegal(ctx); + } + ctx->pc_succ_insn = ctx->base.pc_next + 2; + custom_c_insn_decoded = custom_c_insn_handler(ctx, opcode); + if(custom_c_insn_decoded) {custom_insn_decoded = true;} + } else { + uint32_t opcode32 = opcode; + opcode32 = deposit32(opcode32, 16, 16, translator_lduw(env, &ctx->base, + ctx->base.pc_next + 2)); + ctx->opcode = opcode32; + ctx->pc_succ_insn = ctx->base.pc_next + 4; + custom_insn_decoded = custom_insn_handler(ctx, opcode32); + } +} + +static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode) +{ + /* + * Try to deocde and trans the custom instruction before any others + * This is a bad idea which introduces great performance penalties, + * but we don't have other choices here ... + */ + custom_insn_decoded = false; + custom_c_insn_decoded = false; + if (unlikely(cpu_has_custom_insns)) { + try_decode_custom_insn(env, ctx, opcode); + } + + if (likely(!custom_insn_decoded)) { + if(unlikely(cpu_has_custom_insns)) + ctx->pc_succ_insn = ctx->base.pc_next - !custom_c_insn_decoded ? 4 : 2; + /* check for compressed insn */ + if (extract16(opcode, 0, 2) != 3) { + if (!has_ext(ctx, RVC)) { + gen_exception_illegal(ctx); + } else { + ctx->pc_succ_insn = ctx->base.pc_next + 2; + if (!decode_insn16(ctx, opcode)) { + gen_exception_illegal(ctx); + } + } } else { - ctx->pc_succ_insn = ctx->base.pc_next + 2; - if (!decode_insn16(ctx, opcode)) { + uint32_t opcode32 = opcode; + opcode32 = deposit32(opcode32, 16, 16, + translator_lduw(env, &ctx->base, + ctx->base.pc_next + 2)); + ctx->pc_succ_insn = ctx->base.pc_next + 4; + if (!decode_insn32(ctx, opcode32)) { gen_exception_illegal(ctx); } } - } else { - uint32_t opcode32 = opcode; - opcode32 = deposit32(opcode32, 16, 16, - translator_lduw(env, &ctx->base, - ctx->base.pc_next + 2)); - ctx->pc_succ_insn = ctx->base.pc_next + 4; - if (!decode_insn32(ctx, opcode32)) { - gen_exception_illegal(ctx); - } } } -- 2.25.1