From 172b411257cfb58cfe2131d6c453e06fcf856942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 12 Nov 2011 11:30:03 +0100 Subject: [PATCH] target-rl78: Flesh out disas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- target-78k0/cpu.c | 6 ++ target-78k0/cpu.h | 2 + target-78k0/translate.c | 128 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) diff --git a/target-78k0/cpu.c b/target-78k0/cpu.c index 22dfd1f052..25f9dfeec8 100644 --- a/target-78k0/cpu.c +++ b/target-78k0/cpu.c @@ -73,8 +73,14 @@ void cpu_78k0_list(FILE *f, fprintf_function cpu_fprintf) static void rl78_cpu_initfn(Object *obj) { RL78CPU *cpu = RL78_CPU(obj); + static bool tcg_initialized = false; cpu_exec_init(&cpu->env); + + if (tcg_enabled() && !tcg_initialized) { + tcg_initialized = true; + cpu_rl78_translate_init(); + } } static void rl78_cpu_class_init(ObjectClass *oc, void *data) diff --git a/target-78k0/cpu.h b/target-78k0/cpu.h index ca70898bc3..838a3fc5ef 100644 --- a/target-78k0/cpu.h +++ b/target-78k0/cpu.h @@ -91,6 +91,8 @@ static inline CPU78K0State *cpu_init(const char *cpu_model) return &cpu->env; } +void cpu_rl78_translate_init(void); + int cpu_78k0_exec(CPU78K0State *env); void rl78_cpu_do_interrupt(CPUState *cpu); void rl78_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, diff --git a/target-78k0/translate.c b/target-78k0/translate.c index 1e18b9274a..7ee1bfb03e 100644 --- a/target-78k0/translate.c +++ b/target-78k0/translate.c @@ -23,10 +23,66 @@ #include "tcg-op.h" #include "qemu/log.h" +/* global register indexes */ +static TCGv_ptr cpu_env; + #include "helper.h" #define GEN_HELPER 1 #include "helper.h" +#include "exec/gen-icount.h" + +//#define RL78_DEBUG_DISAS + +#ifdef RL78_DEBUG_DISAS +# define LOG_DISAS(...) printf(__VA_ARGS__) +#else +# define LOG_DISAS(...) do { } while (0) +#endif + +#define LOG_ASM(...) \ + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { \ + qemu_log(__VA_ARGS__); \ + } + +typedef struct DisasContext DisasContext; +struct DisasContext { + uint32_t pc; + int is_jmp; + struct TranslationBlock *tb; +}; + + +void cpu_rl78_translate_init(void) +{ + cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); + +#define GEN_HELPER 2 +#include "helper.h" +} + +typedef int (*OpcodeHandler)(RL78CPU *cpu, uint8_t opcode, DisasContext *s); + +static const OpcodeHandler rl78_1st_map[256] = { +}; + +static void disas_rl78_insn(RL78CPU *cpu, DisasContext *s) +{ + uint8_t opc; + int ins_len; + + opc = cpu_ldub_code(&cpu->env, s->pc); + + if (likely(rl78_1st_map[opc] != NULL)) { + ins_len = rl78_1st_map[opc](cpu, opc, s); + } else { + qemu_log("unimplemented opcode 0x%" PRIx8 "\n", opc); + // TODO + ins_len = 1; + } + + s->pc += ins_len; +} /* Generate intermediate code in gen_opc_buf and gen_opparam_buf for basic block @tb. If @search_pc is %true, also generate PC @@ -35,6 +91,78 @@ static inline void gen_intermediate_code_internal(RL78CPU *cpu, TranslationBlock *tb, bool search_pc) { + CPUState *cs = CPU(cpu); + DisasContext dc; + target_ulong pc_start; + uint16_t *gen_opc_end; + int num_insns, max_insns; + CPUBreakpoint *bp; + int j, lj = -1; + + pc_start = tb->pc; + pc_start &= 0x0fffff; + dc.pc = pc_start; + dc.is_jmp = DISAS_NEXT; + dc.tb = tb; + + gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE; + + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) { + max_insns = CF_COUNT_MASK; + } + + gen_tb_start(); + + do { + if (unlikely(!QTAILQ_EMPTY(&cpu->env.breakpoints))) { + QTAILQ_FOREACH(bp, &cpu->env.breakpoints, entry) { + if (bp->pc == dc.pc) { + // TODO + break; + } + } + } + if (search_pc) { + j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; + if (lj < j) { + lj++; + while (lj < j) { + tcg_ctx.gen_opc_instr_start[lj++] = 0; + } + } + tcg_ctx.gen_opc_pc[lj] = dc.pc; + tcg_ctx.gen_opc_instr_start[lj] = 1; + tcg_ctx.gen_opc_icount[lj] = num_insns; + } + + disas_rl78_insn(cpu, &dc); + + num_insns++; + if (cs->singlestep_enabled) { + // TODO + } + } while (dc.is_jmp == DISAS_NEXT + && tcg_ctx.gen_opc_ptr < gen_opc_end && num_insns < max_insns + && !cs->singlestep_enabled && !singlestep); + + /* Generate the return instruction */ + if (dc.is_jmp != DISAS_TB_JUMP) { + tcg_gen_exit_tb(0); + } + gen_tb_end(tb, num_insns); + *tcg_ctx.gen_opc_ptr = INDEX_op_end; + if (search_pc) { + j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; + lj++; + while (lj <= j) { + tcg_ctx.gen_opc_instr_start[lj++] = 0; + } + } else { + tb->size = dc.pc - pc_start; + tb->icount = num_insns; + } } void gen_intermediate_code(CPU78K0State *env, TranslationBlock *tb)