From: Michael Rolnik <mrolnik@gmail.com>
To: qemu-devel@nongnu.org
Cc: thuth@redhat.com, Michael Rolnik <mrolnik@gmail.com>,
me@xcancerberox.com.ar, richard.henderson@linaro.org,
dovgaluk@ispras.ru, imammedo@redhat.com, philmd@redhat.com,
aleksandar.m.mail@gmail.com
Subject: [PATCH v39 10/22] target/avr: Add instruction translation - CPU main translation function
Date: Wed, 18 Dec 2019 23:03:17 +0200 [thread overview]
Message-ID: <20191218210329.1960-11-mrolnik@gmail.com> (raw)
In-Reply-To: <20191218210329.1960-1-mrolnik@gmail.com>
Co-developed-by: Richard Henderson <richard.henderson@linaro.org>
Co-developed-by: Michael Rolnik <mrolnik@gmail.com>
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
target/avr/translate.c | 234 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 234 insertions(+)
diff --git a/target/avr/translate.c b/target/avr/translate.c
index 46cbcc9305..302d643068 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -2674,3 +2674,237 @@ static bool trans_WDR(DisasContext *ctx, arg_WDR *a)
return true;
}
+
+
+void avr_cpu_tcg_init(void)
+{
+ int i;
+
+#define AVR_REG_OFFS(x) offsetof(CPUAVRState, x)
+ cpu_pc = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(pc_w), "pc");
+ cpu_Cf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregC), "Cf");
+ cpu_Zf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregZ), "Zf");
+ cpu_Nf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregN), "Nf");
+ cpu_Vf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregV), "Vf");
+ cpu_Sf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregS), "Sf");
+ cpu_Hf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregH), "Hf");
+ cpu_Tf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregT), "Tf");
+ cpu_If = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregI), "If");
+ cpu_rampD = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampD), "rampD");
+ cpu_rampX = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampX), "rampX");
+ cpu_rampY = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampY), "rampY");
+ cpu_rampZ = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampZ), "rampZ");
+ cpu_eind = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(eind), "eind");
+ cpu_sp = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sp), "sp");
+ cpu_skip = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(skip), "skip");
+
+ for (i = 0; i < NUMBER_OF_CPU_REGISTERS; i++) {
+ cpu_r[i] = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(r[i]),
+ reg_names[i]);
+ }
+#undef AVR_REG_OFFS
+}
+
+static void translate(DisasContext *ctx)
+{
+ uint32_t opcode = next_word(ctx);
+
+ if (!decode_insn(ctx, opcode)) {
+ gen_helper_unsupported(cpu_env);
+ ctx->bstate = DISAS_NORETURN;
+ }
+}
+
+/* Standardize the cpu_skip condition to NE. */
+static bool canonicalize_skip(DisasContext *ctx)
+{
+ switch (ctx->skip_cond) {
+ case TCG_COND_NEVER:
+ /* Normal case: cpu_skip is known to be false. */
+ return false;
+
+ case TCG_COND_ALWAYS:
+ /*
+ * Breakpoint case: cpu_skip is known to be true, via TB_FLAGS_SKIP.
+ * The breakpoint is on the instruction being skipped, at the start
+ * of the TranslationBlock. No need to update.
+ */
+ return false;
+
+ case TCG_COND_NE:
+ if (ctx->skip_var1 == NULL) {
+ tcg_gen_mov_tl(cpu_skip, ctx->skip_var0);
+ } else {
+ tcg_gen_xor_tl(cpu_skip, ctx->skip_var0, ctx->skip_var1);
+ ctx->skip_var1 = NULL;
+ }
+ break;
+
+ default:
+ /* Convert to a NE condition vs 0. */
+ if (ctx->skip_var1 == NULL) {
+ tcg_gen_setcondi_tl(ctx->skip_cond, cpu_skip, ctx->skip_var0, 0);
+ } else {
+ tcg_gen_setcond_tl(ctx->skip_cond, cpu_skip,
+ ctx->skip_var0, ctx->skip_var1);
+ ctx->skip_var1 = NULL;
+ }
+ ctx->skip_cond = TCG_COND_NE;
+ break;
+ }
+ if (ctx->free_skip_var0) {
+ tcg_temp_free(ctx->skip_var0);
+ ctx->free_skip_var0 = false;
+ }
+ ctx->skip_var0 = cpu_skip;
+ return true;
+}
+
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
+{
+ CPUAVRState *env = cs->env_ptr;
+ DisasContext ctx = {
+ .tb = tb,
+ .cs = cs,
+ .env = env,
+ .memidx = 0,
+ .bstate = DISAS_NEXT,
+ .skip_cond = TCG_COND_NEVER,
+ .singlestep = cs->singlestep_enabled,
+ };
+ target_ulong pc_start = tb->pc / 2;
+ int num_insns = 0;
+
+ if (tb->flags & TB_FLAGS_FULL_ACCESS) {
+ /*
+ * This flag is set by ST/LD instruction we will regenerate it ONLY
+ * with mem/cpu memory access instead of mem access
+ */
+ max_insns = 1;
+ }
+ if (ctx.singlestep) {
+ max_insns = 1;
+ }
+
+ gen_tb_start(tb);
+
+ ctx.npc = pc_start;
+ if (tb->flags & TB_FLAGS_SKIP) {
+ ctx.skip_cond = TCG_COND_ALWAYS;
+ ctx.skip_var0 = cpu_skip;
+ }
+
+ do {
+ TCGLabel *skip_label = NULL;
+
+ /* translate current instruction */
+ tcg_gen_insn_start(ctx.npc);
+ num_insns++;
+
+ /*
+ * this is due to some strange GDB behavior
+ * let's assume main has address 0x100
+ * b main - sets breakpoint at address 0x00000100 (code)
+ * b *0x100 - sets breakpoint at address 0x00800100 (data)
+ */
+ if (unlikely(!ctx.singlestep &&
+ (cpu_breakpoint_test(cs, OFFSET_CODE + ctx.npc * 2, BP_ANY) ||
+ cpu_breakpoint_test(cs, OFFSET_DATA + ctx.npc * 2, BP_ANY)))) {
+ canonicalize_skip(&ctx);
+ tcg_gen_movi_tl(cpu_pc, ctx.npc);
+ gen_helper_debug(cpu_env);
+ goto done_generating;
+ }
+
+ /* Conditionally skip the next instruction, if indicated. */
+ if (ctx.skip_cond != TCG_COND_NEVER) {
+ skip_label = gen_new_label();
+ if (ctx.skip_var0 == cpu_skip) {
+ /*
+ * Copy cpu_skip so that we may zero it before the branch.
+ * This ensures that cpu_skip is non-zero after the label
+ * if and only if the skipped insn itself sets a skip.
+ */
+ ctx.free_skip_var0 = true;
+ ctx.skip_var0 = tcg_temp_new();
+ tcg_gen_mov_tl(ctx.skip_var0, cpu_skip);
+ tcg_gen_movi_tl(cpu_skip, 0);
+ }
+ if (ctx.skip_var1 == NULL) {
+ tcg_gen_brcondi_tl(ctx.skip_cond, ctx.skip_var0, 0, skip_label);
+ } else {
+ tcg_gen_brcond_tl(ctx.skip_cond, ctx.skip_var0,
+ ctx.skip_var1, skip_label);
+ ctx.skip_var1 = NULL;
+ }
+ if (ctx.free_skip_var0) {
+ tcg_temp_free(ctx.skip_var0);
+ ctx.free_skip_var0 = false;
+ }
+ ctx.skip_cond = TCG_COND_NEVER;
+ ctx.skip_var0 = NULL;
+ }
+
+ translate(&ctx);
+
+ if (skip_label) {
+ canonicalize_skip(&ctx);
+ gen_set_label(skip_label);
+ if (ctx.bstate == DISAS_NORETURN) {
+ ctx.bstate = DISAS_CHAIN;
+ }
+ }
+ } while (ctx.bstate == DISAS_NEXT
+ && num_insns < max_insns
+ && (ctx.npc - pc_start) * 2 < TARGET_PAGE_SIZE - 4
+ && !tcg_op_buf_full());
+
+ if (tb->cflags & CF_LAST_IO) {
+ gen_io_end();
+ }
+
+ bool nonconst_skip = canonicalize_skip(&ctx);
+
+ switch (ctx.bstate) {
+ case DISAS_NORETURN:
+ assert(!nonconst_skip);
+ break;
+ case DISAS_NEXT:
+ case DISAS_TOO_MANY:
+ case DISAS_CHAIN:
+ if (!nonconst_skip) {
+ /* Note gen_goto_tb checks singlestep. */
+ gen_goto_tb(&ctx, 1, ctx.npc);
+ break;
+ }
+ tcg_gen_movi_tl(cpu_pc, ctx.npc);
+ /* fall through */
+ case DISAS_LOOKUP:
+ if (!ctx.singlestep) {
+ tcg_gen_lookup_and_goto_ptr();
+ break;
+ }
+ /* fall through */
+ case DISAS_EXIT:
+ if (ctx.singlestep) {
+ gen_helper_debug(cpu_env);
+ } else {
+ tcg_gen_exit_tb(NULL, 0);
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+done_generating:
+ gen_tb_end(tb, num_insns);
+
+ tb->size = (ctx.npc - pc_start) * 2;
+ tb->icount = num_insns;
+}
+
+void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
+ target_ulong *data)
+{
+ env->pc_w = data[0];
+}
--
2.17.2 (Apple Git-113)
next prev parent reply other threads:[~2019-12-18 21:09 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-18 21:03 [PATCH v39 00/22] QEMU AVR 8 bit cores Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 01/22] target/avr: Add outward facing interfaces and core CPU logic Michael Rolnik
2019-12-21 10:53 ` Aleksandar Markovic
2019-12-21 11:22 ` Philippe Mathieu-Daudé
2019-12-21 12:32 ` Aleksandar Markovic
2019-12-18 21:03 ` [PATCH v39 02/22] target/avr: Add instruction helpers Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 03/22] target/avr: Add instruction decoding Michael Rolnik
2019-12-21 11:18 ` Aleksandar Markovic
2019-12-21 15:57 ` Michael Rolnik
2019-12-21 16:21 ` Aleksandar Markovic
2019-12-21 17:15 ` Aleksandar Markovic
2019-12-28 19:31 ` Michael Rolnik
2019-12-29 14:37 ` Aleksandar Markovic
2019-12-18 21:03 ` [PATCH v39 04/22] target/avr: Add instruction translation - Registers definition Michael Rolnik
2019-12-22 15:54 ` Aleksandar Markovic
2019-12-18 21:03 ` [PATCH v39 05/22] target/avr: Add instruction translation - Arithmetic and Logic Instructions Michael Rolnik
2019-12-22 15:41 ` Aleksandar Markovic
2019-12-18 21:03 ` [PATCH v39 06/22] target/avr: Add instruction translation - Branch Instructions Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 07/22] target/avr: Add instruction translation - Data Transfer Instructions Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 08/22] target/avr: Add instruction translation - Bit and Bit-test Instructions Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 09/22] target/avr: Add instruction translation - MCU Control Instructions Michael Rolnik
2019-12-18 21:03 ` Michael Rolnik [this message]
2019-12-18 21:03 ` [PATCH v39 11/22] target/avr: Add instruction disassembly function Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 12/22] target/avr: Add limited support for USART peripheral Michael Rolnik
2019-12-20 15:56 ` Philippe Mathieu-Daudé
2019-12-18 21:03 ` [PATCH v39 13/22] target/avr: Add limited support for 16 bit timer peripheral Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 14/22] target/avr: Add dummy mask device Michael Rolnik
2019-12-23 8:46 ` Aleksandar Markovic
2019-12-28 18:52 ` Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 15/22] target/avr: Add example board configuration Michael Rolnik
2019-12-20 9:51 ` Igor Mammedov
2019-12-20 12:30 ` Michael Rolnik
2019-12-20 15:18 ` Igor Mammedov
2019-12-20 23:12 ` Philippe Mathieu-Daudé
2020-01-21 21:32 ` Philippe Mathieu-Daudé
2019-12-18 21:03 ` [PATCH v39 16/22] target/avr: Add section about AVR into QEMU documentation Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 17/22] target/avr: Register AVR support with the rest of QEMU Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 18/22] target/avr: Add machine none test Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 19/22] target/avr: Update build system Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 20/22] target/avr: Add boot serial test Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 21/22] target/avr: Add Avocado test Michael Rolnik
2019-12-18 21:03 ` [PATCH v39 22/22] target/avr: Update MAINTAINERS file Michael Rolnik
2019-12-23 8:56 ` Aleksandar Markovic
2019-12-23 9:13 ` [PATCH v39 00/22] QEMU AVR 8 bit cores Aleksandar Markovic
2019-12-28 18:01 ` Michael Rolnik
2019-12-28 19:38 ` Aleksandar Markovic
2019-12-28 20:00 ` Michael Rolnik
2019-12-29 14:19 ` Aleksandar Markovic
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191218210329.1960-11-mrolnik@gmail.com \
--to=mrolnik@gmail.com \
--cc=aleksandar.m.mail@gmail.com \
--cc=dovgaluk@ispras.ru \
--cc=imammedo@redhat.com \
--cc=me@xcancerberox.com.ar \
--cc=philmd@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.