[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH v1 1/2] riscv: Add preliminary infra for custom instrcution h
From: |
Ruinland Chuan-Tzu Tsai |
Subject: |
[RFC PATCH v1 1/2] riscv: Add preliminary infra for custom instrcution handling |
Date: |
Thu, 21 Oct 2021 23:11:35 +0800 |
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 <ruinland@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
- [RFC PATCH v1 1/2] riscv: Add preliminary infra for custom instrcution handling,
Ruinland Chuan-Tzu Tsai <=
Re: [RFC PATCH v1 1/2] riscv: Add preliminary infra for custom instrcution handling, Richard Henderson, 2021/10/21