[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 03/18] target-riscv: Add initialization for translat
From: |
Sagar Karandikar |
Subject: |
[Qemu-devel] [PATCH 03/18] target-riscv: Add initialization for translation |
Date: |
Mon, 26 Sep 2016 03:56:33 -0700 |
Add tcg and cpu model initialization
Add gen_intermediate_code function, dummy decode_opc
Add exception helpers necessary for gen_intermediate_code
Signed-off-by: Sagar Karandikar <address@hidden>
---
target-riscv/helper.h | 4 +
target-riscv/op_helper.c | 26 +++++
target-riscv/translate.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 273 insertions(+), 1 deletion(-)
diff --git a/target-riscv/helper.h b/target-riscv/helper.h
index e69de29..0461118 100644
--- a/target-riscv/helper.h
+++ b/target-riscv/helper.h
@@ -0,0 +1,4 @@
+/* Exceptions */
+DEF_HELPER_2(raise_exception, noreturn, env, i32)
+DEF_HELPER_1(raise_exception_debug, noreturn, env)
+DEF_HELPER_3(raise_exception_mbadaddr, noreturn, env, i32, tl)
diff --git a/target-riscv/op_helper.c b/target-riscv/op_helper.c
index c77a520..fd1ef3c 100644
--- a/target-riscv/op_helper.c
+++ b/target-riscv/op_helper.c
@@ -24,6 +24,32 @@
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
+/* Exceptions processing helpers */
+static inline void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env,
+ uint32_t exception, uintptr_t pc)
+{
+ CPUState *cs = CPU(riscv_env_get_cpu(env));
+ qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception);
+ cs->exception_index = exception;
+ cpu_loop_exit_restore(cs, pc);
+}
+
+void helper_raise_exception(CPURISCVState *env, uint32_t exception)
+{
+ do_raise_exception_err(env, exception, 0);
+}
+
+void helper_raise_exception_debug(CPURISCVState *env)
+{
+ do_raise_exception_err(env, EXCP_DEBUG, 0);
+}
+
+void helper_raise_exception_mbadaddr(CPURISCVState *env, uint32_t exception,
+ target_ulong bad_pc) {
+ env->badaddr = bad_pc;
+ do_raise_exception_err(env, exception, 0);
+}
+
#ifndef CONFIG_USER_ONLY
void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type, int mmu_idx,
diff --git a/target-riscv/translate.c b/target-riscv/translate.c
index b50c662..8413c39 100644
--- a/target-riscv/translate.c
+++ b/target-riscv/translate.c
@@ -27,6 +27,35 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#define RISCV_DEBUG_DISAS 0
+
+/* global register indices */
+static TCGv_ptr cpu_env;
+static TCGv cpu_gpr[32], cpu_PC;
+static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
+static TCGv load_res;
+
+#include "exec/gen-icount.h"
+
+typedef struct DisasContext {
+ struct TranslationBlock *tb;
+ target_ulong pc;
+ uint32_t opcode;
+ int singlestep_enabled;
+ int mem_idx;
+ int bstate;
+} DisasContext;
+
+static inline void kill_unknown(DisasContext *ctx, int excp);
+
+enum {
+ BS_NONE = 0, /* When seen outside of translation while loop, indicates
+ need to exit tb due to end of page. */
+ BS_STOP = 1, /* Need to exit tb for syscall, sret, etc. */
+ BS_BRANCH = 2, /* Need to exit tb for branch, jal, etc. */
+};
+
+
static const char * const regnames[] = {
"zero", "ra ", "sp ", "gp ", "tp ", "t0 ", "t1 ", "t2 ",
"s0 ", "s1 ", "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ",
@@ -41,8 +70,160 @@ static const char * const fpr_regnames[] = {
"fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
};
+static inline void generate_exception(DisasContext *ctx, int excp)
+{
+ tcg_gen_movi_tl(cpu_PC, ctx->pc);
+ TCGv_i32 helper_tmp = tcg_const_i32(excp);
+ gen_helper_raise_exception(cpu_env, helper_tmp);
+ tcg_temp_free_i32(helper_tmp);
+}
+
+static inline void generate_exception_mbadaddr(DisasContext *ctx, int excp)
+{
+ tcg_gen_movi_tl(cpu_PC, ctx->pc);
+ TCGv_i32 helper_tmp = tcg_const_i32(excp);
+ gen_helper_raise_exception_mbadaddr(cpu_env, helper_tmp, cpu_PC);
+ tcg_temp_free_i32(helper_tmp);
+}
+
+/* unknown instruction */
+static inline void kill_unknown(DisasContext *ctx, int excp)
+{
+ generate_exception(ctx, excp);
+ ctx->bstate = BS_STOP;
+}
+
+static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
+{
+ if (unlikely(ctx->singlestep_enabled)) {
+ return false;
+ }
+
+#ifndef CONFIG_USER_ONLY
+ return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
+#else
+ return true;
+#endif
+}
+
+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+{
+ if (use_goto_tb(ctx, dest)) {
+ /* chaining is only allowed when the jump is to the same page */
+ tcg_gen_goto_tb(n);
+ tcg_gen_movi_tl(cpu_PC, dest);
+ tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
+ } else {
+ tcg_gen_movi_tl(cpu_PC, dest);
+ if (ctx->singlestep_enabled) {
+ gen_helper_raise_exception_debug(cpu_env);
+ }
+ tcg_gen_exit_tb(0);
+ }
+}
+
+static void decode_opc(CPURISCVState *env, DisasContext *ctx)
+{
+}
+
void gen_intermediate_code(CPURISCVState *env, TranslationBlock *tb)
{
+ RISCVCPU *cpu = riscv_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
+ DisasContext ctx;
+ target_ulong pc_start;
+ target_ulong next_page_start;
+ int num_insns;
+ int max_insns;
+ pc_start = tb->pc;
+ next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+ ctx.pc = pc_start;
+
+ /* once we have GDB, the rest of the translate.c implementation should be
+ ready for singlestep */
+ ctx.singlestep_enabled = cs->singlestep_enabled;
+
+ ctx.tb = tb;
+ ctx.bstate = BS_NONE;
+
+ ctx.mem_idx = cpu_mmu_index(env, false);
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+ gen_tb_start(tb);
+
+ while (ctx.bstate == BS_NONE) {
+ tcg_gen_insn_start(ctx.pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ tcg_gen_movi_tl(cpu_PC, ctx.pc);
+ ctx.bstate = BS_BRANCH;
+ gen_helper_raise_exception_debug(cpu_env);
+ /* The address covered by the breakpoint must be included in
+ [tb->pc, tb->pc + tb->size) in order to for it to be
+ properly cleared -- thus we increment the PC here so that
+ the logic setting tb->size below does the right thing. */
+ ctx.pc += 4;
+ goto done_generating;
+ }
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+ gen_io_start();
+ }
+
+ ctx.opcode = cpu_ldl_code(env, ctx.pc);
+ decode_opc(env, &ctx);
+ ctx.pc += 4;
+
+ if (cs->singlestep_enabled) {
+ break;
+ }
+ if (ctx.pc >= next_page_start) {
+ break;
+ }
+ if (tcg_op_buf_full()) {
+ break;
+ }
+ if (num_insns >= max_insns) {
+ break;
+ }
+ if (singlestep) {
+ break;
+ }
+
+ }
+ if (tb->cflags & CF_LAST_IO) {
+ gen_io_end();
+ }
+ if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
+ if (ctx.bstate == BS_NONE) {
+ tcg_gen_movi_tl(cpu_PC, ctx.pc);
+ }
+ gen_helper_raise_exception_debug(cpu_env);
+ } else {
+ switch (ctx.bstate) {
+ case BS_STOP:
+ gen_goto_tb(&ctx, 0, ctx.pc);
+ break;
+ case BS_NONE: /* handle end of page - DO NOT CHAIN. See gen_goto_tb. */
+ tcg_gen_movi_tl(cpu_PC, ctx.pc);
+ tcg_gen_exit_tb(0);
+ break;
+ case BS_BRANCH: /* ops using BS_BRANCH generate own exit seq */
+ default:
+ break;
+ }
+ }
+done_generating:
+ gen_tb_end(tb, num_insns);
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
}
void riscv_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
@@ -78,6 +259,34 @@ void riscv_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf,
void riscv_tcg_init(void)
{
+ int i;
+ static int inited;
+
+ /* Initialize various static tables. */
+ if (inited) {
+ return;
+ }
+
+ cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+
+ /* WARNING: cpu_gpr[0] is not allocated ON PURPOSE. Do not use it. */
+ /* Use the gen_set_gpr and gen_get_gpr helper functions when accessing */
+ /* registers, unless you specifically block reads/writes to reg 0 */
+ TCGV_UNUSED(cpu_gpr[0]);
+ for (i = 1; i < 32; i++) {
+ cpu_gpr[i] = tcg_global_mem_new(cpu_env,
+ offsetof(CPURISCVState, gpr[i]), regnames[i]);
+ }
+
+ for (i = 0; i < 32; i++) {
+ cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
+ offsetof(CPURISCVState, fpr[i]), fpr_regnames[i]);
+ }
+
+ cpu_PC = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, PC), "PC");
+ load_res = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_res),
+ "load_res");
+ inited = 1;
}
#define MCPUID_RV64I (2L << (TARGET_LONG_BITS - 2))
@@ -111,6 +320,17 @@ static const riscv_def_t riscv_defs[] = {
},
};
+static const riscv_def_t *cpu_riscv_find_by_name(const char *name)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(riscv_defs); i++) {
+ if (strcasecmp(name, riscv_defs[i].name) == 0) {
+ return &riscv_defs[i];
+ }
+ }
+ return NULL;
+}
+
void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf)
{
int i;
@@ -121,7 +341,29 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf)
RISCVCPU *cpu_riscv_init(const char *cpu_model)
{
- return NULL;
+ RISCVCPU *cpu;
+ CPURISCVState *env;
+ const riscv_def_t *def;
+
+ def = cpu_riscv_find_by_name(cpu_model);
+ if (!def) {
+ return NULL;
+ }
+ cpu = RISCV_CPU(object_new(TYPE_RISCV_CPU));
+ env = &cpu->env;
+ env->cpu_model = def;
+
+ memset(env->csr, 0, 4096 * sizeof(target_ulong));
+ env->priv = PRV_M;
+
+ /* set mcpuid from def */
+ env->csr[CSR_MISA] = def->init_misa_reg;
+ object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
+
+ /* fpu flags: */
+ set_default_nan_mode(1, &env->fp_status);
+
+ return cpu;
}
void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
--
2.9.3
- [Qemu-devel] [PATCH 06/18] target-riscv: Add JALR, Branch Instructions, (continued)
- [Qemu-devel] [PATCH 06/18] target-riscv: Add JALR, Branch Instructions, Sagar Karandikar, 2016/09/26
- [Qemu-devel] [PATCH 01/18] target-riscv: Add RISC-V target stubs and Maintainer, Sagar Karandikar, 2016/09/26
- [Qemu-devel] [PATCH 15/18] target-riscv: Interrupt Handling, Sagar Karandikar, 2016/09/26
- [Qemu-devel] [PATCH 07/18] target-riscv: Add Loads/Stores, FP Loads/Stores, Sagar Karandikar, 2016/09/26
- [Qemu-devel] [PATCH 08/18] target-riscv: Add Atomic Instructions, Sagar Karandikar, 2016/09/26
- [Qemu-devel] [PATCH 03/18] target-riscv: Add initialization for translation,
Sagar Karandikar <=
- [Qemu-devel] [PATCH 14/18] target-riscv: softmmu/address translation support, Sagar Karandikar, 2016/09/26
- [Qemu-devel] [PATCH 16/18] target-riscv: Timer Support, Sagar Karandikar, 2016/09/26
- [Qemu-devel] [PATCH 12/18] target-riscv: Add system instructions, Sagar Karandikar, 2016/09/26
- Re: [Qemu-devel] [PATCH 12/18] target-riscv: Add system instructions, Richard Henderson, 2016/09/26