All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v18 00/13] AVR target
@ 2016-09-16 22:00 Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 01/13] target-avr: AVR cores support is added Richard Henderson
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

This is Michael's v17, with some adjustments of my own:

(1) Fix the whitespace errors reported by "git am",
(2) Replace the utf-8 characters with normal ascii,
(3) Ditch the separate compilation of translate.c.

I retained the two separate files that could be regenerated
from the included cpugen program, but merged in translate-insn.c.
Not that it matters, but the code generated is about 3k smaller.


r~


Michael Rolnik (9):
  target-avr: AVR cores support is added.
  target-avr: adding AVR CPU features/flavors
  target-avr: adding a sample AVR board
  target-avr: adding instructions encodings
  target-avr: adding AVR interrupt handling
  target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported
    instructions
  target-avr: adding instruction translation
  target-avr: instruction decoder generator
  target-avr: adding instruction decoder

Richard Henderson (4):
  target-avr: Put env pointer in DisasContext
  target-avr: Put all translation code into one compilation unit
  target-avr: Respect .inc.c convention
  target-avr: Merge translate-inst.inc.c into translate.c

 MAINTAINERS                                |    6 +
 arch_init.c                                |    2 +
 configure                                  |    5 +
 default-configs/avr-softmmu.mak            |   21 +
 hw/avr/Makefile.objs                       |   21 +
 hw/avr/sample.c                            |  111 ++
 include/disas/bfd.h                        |    6 +
 include/sysemu/arch_init.h                 |    1 +
 target-avr/Makefile.objs                   |   23 +
 target-avr/cpu-qom.h                       |   84 +
 target-avr/cpu.c                           |  602 ++++++
 target-avr/cpu.h                           |  237 +++
 target-avr/cpugen/CMakeLists.txt           |   38 +
 target-avr/cpugen/README.md                |   17 +
 target-avr/cpugen/cpu/avr.yaml             |  213 ++
 target-avr/cpugen/src/CMakeLists.txt       |   62 +
 target-avr/cpugen/src/cpugen.cpp           |  457 +++++
 target-avr/cpugen/src/utils.cpp            |   26 +
 target-avr/cpugen/src/utils.h              |   78 +
 target-avr/cpugen/xsl/decode.c.xsl         |  103 +
 target-avr/cpugen/xsl/translate-inst.h.xsl |  118 ++
 target-avr/cpugen/xsl/utils.xsl            |  108 ++
 target-avr/decode.inc.c                    |  689 +++++++
 target-avr/gdbstub.c                       |   85 +
 target-avr/helper.c                        |  355 ++++
 target-avr/helper.h                        |   28 +
 target-avr/machine.c                       |  114 ++
 target-avr/translate-inst.h                |  691 +++++++
 target-avr/translate.c                     | 2911 ++++++++++++++++++++++++++++
 29 files changed, 7212 insertions(+)
 create mode 100644 default-configs/avr-softmmu.mak
 create mode 100644 hw/avr/Makefile.objs
 create mode 100644 hw/avr/sample.c
 create mode 100644 target-avr/Makefile.objs
 create mode 100644 target-avr/cpu-qom.h
 create mode 100644 target-avr/cpu.c
 create mode 100644 target-avr/cpu.h
 create mode 100644 target-avr/cpugen/CMakeLists.txt
 create mode 100644 target-avr/cpugen/README.md
 create mode 100644 target-avr/cpugen/cpu/avr.yaml
 create mode 100644 target-avr/cpugen/src/CMakeLists.txt
 create mode 100644 target-avr/cpugen/src/cpugen.cpp
 create mode 100644 target-avr/cpugen/src/utils.cpp
 create mode 100644 target-avr/cpugen/src/utils.h
 create mode 100644 target-avr/cpugen/xsl/decode.c.xsl
 create mode 100644 target-avr/cpugen/xsl/translate-inst.h.xsl
 create mode 100644 target-avr/cpugen/xsl/utils.xsl
 create mode 100644 target-avr/decode.inc.c
 create mode 100644 target-avr/gdbstub.c
 create mode 100644 target-avr/helper.c
 create mode 100644 target-avr/helper.h
 create mode 100644 target-avr/machine.c
 create mode 100644 target-avr/translate-inst.h
 create mode 100644 target-avr/translate.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 01/13] target-avr: AVR cores support is added.
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 02/13] target-avr: adding AVR CPU features/flavors Richard Henderson
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

    1. basic CPU structure
    2. registers
    3. no instructions
    4. saving sreg, rampD, rampX, rampY, rampD, eind in HW representation

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-2-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 MAINTAINERS                     |   5 +
 arch_init.c                     |   2 +
 configure                       |   5 +
 default-configs/avr-softmmu.mak |  21 +++
 include/disas/bfd.h             |   6 +
 include/sysemu/arch_init.h      |   1 +
 target-avr/Makefile.objs        |  23 ++++
 target-avr/cpu-qom.h            |  84 ++++++++++++
 target-avr/cpu.c                | 291 ++++++++++++++++++++++++++++++++++++++++
 target-avr/cpu.h                | 179 ++++++++++++++++++++++++
 target-avr/gdbstub.c            |  85 ++++++++++++
 target-avr/helper.c             |  88 ++++++++++++
 target-avr/helper.h             |  21 +++
 target-avr/machine.c            | 114 ++++++++++++++++
 target-avr/translate.c          | 255 +++++++++++++++++++++++++++++++++++
 target-avr/translate.h          | 114 ++++++++++++++++
 16 files changed, 1294 insertions(+)
 create mode 100644 default-configs/avr-softmmu.mak
 create mode 100644 target-avr/Makefile.objs
 create mode 100644 target-avr/cpu-qom.h
 create mode 100644 target-avr/cpu.c
 create mode 100644 target-avr/cpu.h
 create mode 100644 target-avr/gdbstub.c
 create mode 100644 target-avr/helper.c
 create mode 100644 target-avr/helper.h
 create mode 100644 target-avr/machine.c
 create mode 100644 target-avr/translate.c
 create mode 100644 target-avr/translate.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7d43026..e526316 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -111,6 +111,11 @@ F: disas/arm.c
 F: disas/arm-a64.cc
 F: disas/libvixl/
 
+AVR
+M: Michael Rolnik <mrolnik@gmail.com>
+S: Maintained
+F: target-avr/
+
 CRIS
 M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
 S: Maintained
diff --git a/arch_init.c b/arch_init.c
index fa05973..be6e6de 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -80,6 +80,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_UNICORE32
 #elif defined(TARGET_TRICORE)
 #define QEMU_ARCH QEMU_ARCH_TRICORE
+#elif defined(TARGET_AVR)
+#define QEMU_ARCH QEMU_ARCH_AVR
 #endif
 
 const uint32_t arch_type = QEMU_ARCH;
diff --git a/configure b/configure
index 7d083bd..737a22e 100755
--- a/configure
+++ b/configure
@@ -5696,6 +5696,8 @@ case "$target_name" in
     bflt="yes"
     gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
   ;;
+  avr)
+  ;;
   cris)
   ;;
   lm32)
@@ -5894,6 +5896,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
       disas_config "ARM_A64"
     fi
   ;;
+  avr)
+    disas_config "AVR"
+  ;;
   cris)
     disas_config "CRIS"
   ;;
diff --git a/default-configs/avr-softmmu.mak b/default-configs/avr-softmmu.mak
new file mode 100644
index 0000000..003465d
--- /dev/null
+++ b/default-configs/avr-softmmu.mak
@@ -0,0 +1,21 @@
+#
+#  QEMU AVR CPU
+#
+#  Copyright (c) 2016 Michael Rolnik
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, see
+#  <http://www.gnu.org/licenses/lgpl-2.1.html>
+#
+
+# Default configuration for avr-softmmu
diff --git a/include/disas/bfd.h b/include/disas/bfd.h
index 8a3488c..8ccd108 100644
--- a/include/disas/bfd.h
+++ b/include/disas/bfd.h
@@ -213,6 +213,12 @@ enum bfd_architecture
 #define bfd_mach_m32r          0  /* backwards compatibility */
   bfd_arch_mn10200,    /* Matsushita MN10200 */
   bfd_arch_mn10300,    /* Matsushita MN10300 */
+  bfd_arch_avr,       /* Atmel AVR microcontrollers.  */
+#define bfd_mach_avr1          1
+#define bfd_mach_avr2          2
+#define bfd_mach_avr3          3
+#define bfd_mach_avr4          4
+#define bfd_mach_avr5          5
   bfd_arch_cris,       /* Axis CRIS */
 #define bfd_mach_cris_v0_v10   255
 #define bfd_mach_cris_v32      32
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 1c9dad1..7c9edbf 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -23,6 +23,7 @@ enum {
     QEMU_ARCH_UNICORE32 = (1 << 14),
     QEMU_ARCH_MOXIE = (1 << 15),
     QEMU_ARCH_TRICORE = (1 << 16),
+    QEMU_ARCH_AVR = (1 << 17),
 };
 
 extern const uint32_t arch_type;
diff --git a/target-avr/Makefile.objs b/target-avr/Makefile.objs
new file mode 100644
index 0000000..48233ef
--- /dev/null
+++ b/target-avr/Makefile.objs
@@ -0,0 +1,23 @@
+#
+#  QEMU AVR CPU
+#
+#  Copyright (c) 2016 Michael Rolnik
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, see
+#  <http://www.gnu.org/licenses/lgpl-2.1.html>
+#
+
+obj-y += translate.o cpu.o helper.o
+obj-y += gdbstub.o
+obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-avr/cpu-qom.h b/target-avr/cpu-qom.h
new file mode 100644
index 0000000..b5cd5a7
--- /dev/null
+++ b/target-avr/cpu-qom.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#ifndef QEMU_AVR_CPU_QOM_H
+#define QEMU_AVR_CPU_QOM_H
+
+#include "qom/cpu.h"
+
+#define TYPE_AVR_CPU "avr"
+
+#define AVR_CPU_CLASS(klass) \
+                    OBJECT_CLASS_CHECK(AVRCPUClass, (klass), TYPE_AVR_CPU)
+#define AVR_CPU(obj) \
+                    OBJECT_CHECK(AVRCPU, (obj), TYPE_AVR_CPU)
+#define AVR_CPU_GET_CLASS(obj) \
+                    OBJECT_GET_CLASS(AVRCPUClass, (obj), TYPE_AVR_CPU)
+
+/**
+ *  AVRCPUClass:
+ *  @parent_realize: The parent class' realize handler.
+ *  @parent_reset: The parent class' reset handler.
+ *  @vr: Version Register value.
+ *
+ *  A AVR CPU model.
+ */
+typedef struct AVRCPUClass {
+    CPUClass parent_class;
+
+    DeviceRealize parent_realize;
+    void (*parent_reset)(CPUState *cpu);
+} AVRCPUClass;
+
+/**
+ *  AVRCPU:
+ *  @env: #CPUAVRState
+ *
+ *  A AVR CPU.
+ */
+typedef struct AVRCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUAVRState env;
+} AVRCPU;
+
+static inline AVRCPU *avr_env_get_cpu(CPUAVRState *env)
+{
+    return container_of(env, AVRCPU, env);
+}
+
+#define ENV_GET_CPU(e) CPU(avr_env_get_cpu(e))
+#define ENV_OFFSET offsetof(AVRCPU, env)
+
+#ifndef CONFIG_USER_ONLY
+extern const struct VMStateDescription vms_avr_cpu;
+#endif
+
+void avr_cpu_do_interrupt(CPUState *cpu);
+bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
+void avr_cpu_dump_state(CPUState *cs, FILE *f,
+                            fprintf_function cpu_fprintf, int flags);
+hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
+#endif
diff --git a/target-avr/cpu.c b/target-avr/cpu.c
new file mode 100644
index 0000000..ed2b1b8
--- /dev/null
+++ b/target-avr/cpu.c
@@ -0,0 +1,291 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "qemu-common.h"
+#include "migration/vmstate.h"
+
+static void avr_cpu_set_pc(CPUState *cs, vaddr value)
+{
+    AVRCPU *cpu = AVR_CPU(cs);
+
+    cpu->env.pc_w = value / 2; /* internally PC points to words */
+}
+
+static bool avr_cpu_has_work(CPUState *cs)
+{
+    AVRCPU *cpu = AVR_CPU(cs);
+    CPUAVRState *env = &cpu->env;
+
+    return (cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_RESET))
+            && cpu_interrupts_enabled(env);
+}
+
+static void avr_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    AVRCPU *cpu = AVR_CPU(cs);
+    CPUAVRState *env = &cpu->env;
+
+    env->pc_w = tb->pc / 2; /* internally PC points to words */
+}
+
+static void avr_cpu_reset(CPUState *s)
+{
+    AVRCPU *cpu = AVR_CPU(s);
+    AVRCPUClass *mcc = AVR_CPU_GET_CLASS(cpu);
+    CPUAVRState *env = &cpu->env;
+
+    mcc->parent_reset(s);
+
+    env->pc_w = 0;
+    env->sregI = 1;
+    env->sregC = 0;
+    env->sregZ = 0;
+    env->sregN = 0;
+    env->sregV = 0;
+    env->sregS = 0;
+    env->sregH = 0;
+    env->sregT = 0;
+
+    env->rampD = 0;
+    env->rampX = 0;
+    env->rampY = 0;
+    env->rampZ = 0;
+    env->eind = 0;
+    env->sp = 0;
+
+    memset(env->r, 0, sizeof(env->r));
+
+    tlb_flush(s, 1);
+}
+
+static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+{
+    info->mach = bfd_arch_avr;
+    info->print_insn = NULL;
+}
+
+static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+    CPUState *cs = CPU(dev);
+    AVRCPUClass *mcc = AVR_CPU_GET_CLASS(dev);
+
+    qemu_init_vcpu(cs);
+    cpu_reset(cs);
+
+    mcc->parent_realize(dev, errp);
+}
+
+static void avr_cpu_set_int(void *opaque, int irq, int level)
+{
+    AVRCPU *cpu = opaque;
+    CPUAVRState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+
+    uint64_t mask = (1ull << irq);
+    if (level) {
+        env->intsrc |= mask;
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+    } else {
+        env->intsrc &= ~mask;
+        if (env->intsrc == 0) {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
+    }
+}
+
+static void avr_cpu_initfn(Object *obj)
+{
+    CPUState *cs = CPU(obj);
+    AVRCPU *cpu = AVR_CPU(obj);
+    static int inited;
+
+    cs->env_ptr = &cpu->env;
+    cpu_exec_init(cs, &error_abort);
+
+#ifndef CONFIG_USER_ONLY
+    qdev_init_gpio_in(DEVICE(cpu), avr_cpu_set_int, 37);
+#endif
+
+    if (tcg_enabled() && !inited) {
+        inited = 1;
+        avr_translate_init();
+    }
+}
+
+static ObjectClass *avr_cpu_class_by_name(const char *cpu_model)
+{
+    ObjectClass *oc;
+    char *typename;
+    char **cpuname;
+
+    if (!cpu_model) {
+        return NULL;
+    }
+
+    cpuname = g_strsplit(cpu_model, ",", 1);
+    typename = g_strdup_printf("%s-" TYPE_AVR_CPU, cpuname[0]);
+    oc = object_class_by_name(typename);
+
+    g_strfreev(cpuname);
+    g_free(typename);
+
+    if (!oc
+        || !object_class_dynamic_cast(oc, TYPE_AVR_CPU)
+        || object_class_is_abstract(oc)) {
+        return NULL;
+    }
+
+    return oc;
+}
+
+static void avr_cpu_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(oc);
+    AVRCPUClass *mcc = AVR_CPU_CLASS(oc);
+
+    mcc->parent_realize = dc->realize;
+    dc->realize = avr_cpu_realizefn;
+
+    mcc->parent_reset = cc->reset;
+    cc->reset = avr_cpu_reset;
+
+    cc->class_by_name = avr_cpu_class_by_name;
+
+    cc->has_work = avr_cpu_has_work;
+    cc->do_interrupt = avr_cpu_do_interrupt;
+    cc->cpu_exec_interrupt = avr_cpu_exec_interrupt;
+    cc->dump_state = avr_cpu_dump_state;
+    cc->set_pc = avr_cpu_set_pc;
+#if !defined(CONFIG_USER_ONLY)
+    cc->memory_rw_debug = avr_cpu_memory_rw_debug;
+#endif
+#ifdef CONFIG_USER_ONLY
+    cc->handle_mmu_fault = avr_cpu_handle_mmu_fault;
+#else
+    cc->get_phys_page_debug = avr_cpu_get_phys_page_debug;
+    cc->vmsd = &vms_avr_cpu;
+#endif
+    cc->disas_set_info = avr_cpu_disas_set_info;
+    cc->synchronize_from_tb = avr_cpu_synchronize_from_tb;
+    cc->gdb_read_register = avr_cpu_gdb_read_register;
+    cc->gdb_write_register = avr_cpu_gdb_write_register;
+    cc->gdb_num_core_regs = 35;
+
+/*
+ * Reason: avr_cpu_initfn() calls cpu_exec_init(), which saves
+ * the object in cpus -> dangling pointer after final
+ * object_unref().
+ */
+    dc->cannot_destroy_with_object_finalize_yet = true;
+}
+
+typedef struct AVRCPUInfo {
+    const char *name;
+    void (*initfn)(Object *obj);
+} AVRCPUInfo;
+
+static const AVRCPUInfo avr_cpus[] = {
+};
+
+static gint avr_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+    ObjectClass *class_a = (ObjectClass *)a;
+    ObjectClass *class_b = (ObjectClass *)b;
+    const char *name_a;
+    const char *name_b;
+
+    name_a = object_class_get_name(class_a);
+    name_b = object_class_get_name(class_b);
+
+    return strcmp(name_a, name_b);
+}
+
+static void avr_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    ObjectClass *oc = data;
+    CPUListState *s = user_data;
+    const char *typename;
+    char *name;
+
+    typename = object_class_get_name(oc);
+    name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_AVR_CPU));
+    (*s->cpu_fprintf)(s->file, "  %s\n", name);
+    g_free(name);
+}
+
+void avr_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    CPUListState s = {
+        .file = f,
+        .cpu_fprintf = cpu_fprintf,
+    };
+    GSList *list;
+
+    list = object_class_get_list(TYPE_AVR_CPU, false);
+    list = g_slist_sort(list, avr_cpu_list_compare);
+    (*cpu_fprintf)(f, "Available CPUs:\n");
+    g_slist_foreach(list, avr_cpu_list_entry, &s);
+    g_slist_free(list);
+}
+
+AVRCPU *cpu_avr_init(const char *cpu_model)
+{
+    return AVR_CPU(cpu_generic_init(TYPE_AVR_CPU, cpu_model));
+}
+
+static void cpu_register(const AVRCPUInfo *info)
+{
+    TypeInfo type_info = {
+        .parent = TYPE_AVR_CPU,
+        .instance_size = sizeof(AVRCPU),
+        .instance_init = info->initfn,
+        .class_size = sizeof(AVRCPUClass),
+    };
+
+    type_info.name = g_strdup_printf("%s-" TYPE_AVR_CPU, info->name);
+    type_register(&type_info);
+    g_free((void *)type_info.name);
+}
+
+static const TypeInfo avr_cpu_type_info = {
+    .name = TYPE_AVR_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(AVRCPU),
+    .instance_init = avr_cpu_initfn,
+    .class_size = sizeof(AVRCPUClass),
+    .class_init = avr_cpu_class_init,
+    .abstract = true,
+};
+
+static void avr_cpu_register_types(void)
+{
+    int i;
+    type_register_static(&avr_cpu_type_info);
+
+    for (i = 0; i < ARRAY_SIZE(avr_cpus); i++) {
+        cpu_register(&avr_cpus[i]);
+    }
+}
+
+type_init(avr_cpu_register_types)
diff --git a/target-avr/cpu.h b/target-avr/cpu.h
new file mode 100644
index 0000000..fb05216
--- /dev/null
+++ b/target-avr/cpu.h
@@ -0,0 +1,179 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#if !defined(CPU_AVR_H)
+#define CPU_AVR_H
+
+#include "qemu-common.h"
+
+#define TARGET_LONG_BITS 32
+
+#define CPUArchState struct CPUAVRState
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat.h"
+
+/*
+ *  TARGET_PAGE_BITS cannot be more than 8 bits because
+ *  1.  all IO registers occupy [0x0000 .. 0x00ff] address range, and they
+ *      should be implemented as a device and not memory
+ *  2.  SRAM starts at the address 0x0100
+ */
+#define TARGET_PAGE_BITS 8
+#define TARGET_PHYS_ADDR_SPACE_BITS 24
+#define TARGET_VIRT_ADDR_SPACE_BITS 24
+#define NB_MMU_MODES 2
+
+/*
+ *  AVR has two memory spaces, data & code.
+ *  e.g. both have 0 address
+ *  ST/LD instructions access data space
+ *  LPM/SPM and instruction fetching access code memory space
+ */
+#define MMU_CODE_IDX 0
+#define MMU_DATA_IDX 1
+
+#define EXCP_RESET 1
+#define EXCP_INT(n) (EXCP_RESET + (n) + 1)
+
+#define PHYS_ADDR_MASK 0xfff00000
+
+#define PHYS_BASE_CODE 0x00000000
+#define PHYS_BASE_DATA 0x00800000
+#define PHYS_BASE_REGS 0x10000000
+
+#define VIRT_BASE_CODE 0x00000000
+#define VIRT_BASE_DATA 0x00000000
+#define VIRT_BASE_REGS 0x00000000
+
+/*
+ *  there are two groups of registers
+ *  1. CPU regs     - accessible by LD/ST and CPU itself
+ *  2. CPU IO regs  - accessible by LD/ST and IN/OUT
+ */
+#define AVR_CPU_REGS 0x0020
+#define AVR_CPU_IO_REGS 0x0040
+#define AVR_REGS (AVR_CPU_IO_REGS + AVR_CPU_REGS)
+
+#define AVR_CPU_REGS_BASE 0x0000
+#define AVR_CPU_IO_REGS_BASE (AVR_CPU_REGS_BASE + AVR_CPU_REGS)
+
+#define AVR_CPU_REGS_LAST (AVR_CPU_REGS_BASE + AVR_CPU_REGS - 1)
+#define AVR_CPU_IO_REGS_LAST (AVR_CPU_IO_REGS_BASE + AVR_CPU_IO_REGS - 1)
+
+typedef struct CPUAVRState CPUAVRState;
+
+struct CPUAVRState {
+    uint32_t pc_w; /* 0x003fffff up to 22 bits */
+
+    uint32_t sregC; /* 0x00000001 1 bits */
+    uint32_t sregZ; /* 0x0000ffff 16 bits, negative logic */
+    uint32_t sregN; /* 0x00000001 1 bits */
+    uint32_t sregV; /* 0x00000001 1 bits */
+    uint32_t sregS; /* 0x00000001 1 bits */
+    uint32_t sregH; /* 0x00000001 1 bits */
+    uint32_t sregT; /* 0x00000001 1 bits */
+    uint32_t sregI; /* 0x00000001 1 bits */
+
+    uint32_t rampD; /* 0x00ff0000 8 bits */
+    uint32_t rampX; /* 0x00ff0000 8 bits */
+    uint32_t rampY; /* 0x00ff0000 8 bits */
+    uint32_t rampZ; /* 0x00ff0000 8 bits */
+    uint32_t eind; /* 0x00ff0000 8 bits */
+
+    uint32_t r[AVR_CPU_REGS];
+                     /* 8 bits each */
+    uint32_t sp; /* 16 bits */
+
+    uint64_t intsrc; /* interrupt sources */
+
+    /* Those resources are used only in QEMU core */
+    CPU_COMMON
+};
+
+#define cpu_list avr_cpu_list
+#define cpu_signal_handler cpu_avr_signal_handler
+
+#include "exec/cpu-all.h"
+#include "cpu-qom.h"
+
+static inline int cpu_mmu_index(CPUAVRState *env, bool ifetch)
+{
+    return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX;
+}
+
+void avr_translate_init(void);
+
+AVRCPU *cpu_avr_init(const char *cpu_model);
+
+#define cpu_init(cpu_model) CPU(cpu_avr_init(cpu_model))
+
+void avr_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+int cpu_avr_exec(CPUState *cpu);
+int cpu_avr_signal_handler(int host_signum, void *pinfo, void *puc);
+int avr_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
+                                int mmu_idx);
+int avr_cpu_memory_rw_debug(CPUState *cs, vaddr address, uint8_t *buf,
+                                int len, bool is_write);
+
+static inline void cpu_get_tb_cpu_state(CPUAVRState *env, target_ulong *pc,
+                                target_ulong *cs_base, uint32_t *pflags)
+{
+    uint32_t flags = 0;
+
+    *pc = env->pc_w * 2;
+    *cs_base = 0;
+    *pflags = flags;
+}
+
+static inline int cpu_interrupts_enabled(CPUAVRState *env)
+{
+    return env->sregI != 0;
+}
+
+static inline uint8_t cpu_get_sreg(CPUAVRState *env)
+{
+    uint8_t sreg;
+    sreg = (env->sregC & 0x01) << 0
+         | (env->sregZ == 0 ? 1 : 0) << 1
+         | (env->sregN) << 2
+         | (env->sregV) << 3
+         | (env->sregS) << 4
+         | (env->sregH) << 5
+         | (env->sregT) << 6
+         | (env->sregI) << 7;
+    return sreg;
+}
+
+static inline void cpu_set_sreg(CPUAVRState *env, uint8_t sreg)
+{
+    env->sregC = (sreg >> 0) & 0x01;
+    env->sregZ = (sreg >> 1) & 0x01 ? 0 : 1;
+    env->sregN = (sreg >> 2) & 0x01;
+    env->sregV = (sreg >> 3) & 0x01;
+    env->sregS = (sreg >> 4) & 0x01;
+    env->sregH = (sreg >> 5) & 0x01;
+    env->sregT = (sreg >> 6) & 0x01;
+    env->sregI = (sreg >> 7) & 0x01;
+}
+
+#include "exec/exec-all.h"
+
+#endif /* !defined (CPU_AVR_H) */
diff --git a/target-avr/gdbstub.c b/target-avr/gdbstub.c
new file mode 100644
index 0000000..537dc72
--- /dev/null
+++ b/target-avr/gdbstub.c
@@ -0,0 +1,85 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int avr_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+    AVRCPU *cpu = AVR_CPU(cs);
+    CPUAVRState *env = &cpu->env;
+
+    /*  R */
+    if (n < 32) {
+        return gdb_get_reg8(mem_buf, env->r[n]);
+    }
+
+    /*  SREG */
+    if (n == 32) {
+        uint8_t sreg = cpu_get_sreg(env);
+
+        return gdb_get_reg8(mem_buf, sreg);
+    }
+
+    /*  SP */
+    if (n == 33) {
+        return gdb_get_reg16(mem_buf, env->sp & 0x0000ffff);
+    }
+
+    /*  PC */
+    if (n == 34) {
+        return gdb_get_reg32(mem_buf, env->pc_w * 2);
+    }
+
+    return 0;
+}
+
+int avr_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+    AVRCPU *cpu = AVR_CPU(cs);
+    CPUAVRState *env = &cpu->env;
+
+    /*  R */
+    if (n < 32) {
+        env->r[n] = *mem_buf;
+        return 1;
+    }
+
+    /*  SREG */
+    if (n == 32) {
+        cpu_set_sreg(env, *mem_buf);
+        return 1;
+    }
+
+    /*  SP */
+    if (n == 33) {
+        env->sp = lduw_p(mem_buf);
+        return 2;
+    }
+
+    /*  PC */
+    if (n == 34) {
+        env->pc_w = ldl_p(mem_buf) / 2;
+        return 4;
+    }
+
+    return 0;
+}
diff --git a/target-avr/helper.c b/target-avr/helper.c
new file mode 100644
index 0000000..c187193
--- /dev/null
+++ b/target-avr/helper.c
@@ -0,0 +1,88 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+
+#include "cpu.h"
+#include "hw/irq.h"
+#include "include/hw/sysbus.h"
+#include "include/sysemu/sysemu.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+
+bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+    bool ret = false;
+    return ret;
+}
+
+void avr_cpu_do_interrupt(CPUState *cs)
+{
+}
+
+int avr_cpu_memory_rw_debug(CPUState *cs, vaddr addr, uint8_t *buf,
+                                int len, bool is_write)
+{
+    return cpu_memory_rw_debug(cs, addr, buf, len, is_write);
+}
+
+hwaddr avr_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+    return addr; /* I assume 1:1 address correspondance */
+}
+
+int avr_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int mmu_idx)
+{
+    /* currently it's assumed that this will never happen */
+    cs->exception_index = EXCP_DEBUG;
+    cpu_dump_state(cs, stderr, fprintf, 0);
+    return 1;
+}
+
+void tlb_fill(CPUState *cs, target_ulong vaddr, MMUAccessType access_type,
+                                int mmu_idx, uintptr_t retaddr)
+{
+    target_ulong page_size = TARGET_PAGE_SIZE;
+    int prot = 0;
+    MemTxAttrs attrs = {};
+    uint32_t paddr;
+
+    vaddr &= TARGET_PAGE_MASK;
+
+    if (mmu_idx == MMU_CODE_IDX) {
+        paddr = PHYS_BASE_CODE + vaddr - VIRT_BASE_CODE;
+        prot = PAGE_READ | PAGE_EXEC;
+    } else {
+        paddr = PHYS_BASE_DATA + vaddr - VIRT_BASE_DATA;
+        prot = PAGE_READ | PAGE_WRITE;
+    }
+
+    tlb_set_page_with_attrs(cs, vaddr, paddr, attrs, prot, mmu_idx, page_size);
+}
+
+void helper_debug(CPUAVRState *env)
+{
+    CPUState *cs = CPU(avr_env_get_cpu(env));
+
+    cs->exception_index = EXCP_DEBUG;
+    cpu_loop_exit(cs);
+}
diff --git a/target-avr/helper.h b/target-avr/helper.h
new file mode 100644
index 0000000..b5ef3bf
--- /dev/null
+++ b/target-avr/helper.h
@@ -0,0 +1,21 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+DEF_HELPER_1(debug, void, env)
diff --git a/target-avr/machine.c b/target-avr/machine.c
new file mode 100644
index 0000000..5b4e46c
--- /dev/null
+++ b/target-avr/machine.c
@@ -0,0 +1,114 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "cpu.h"
+#include "hw/boards.h"
+#include "migration/qemu-file.h"
+
+static int get_sreg(QEMUFile *f, void *opaque, size_t size)
+{
+    CPUAVRState *env = opaque;
+    uint8_t sreg;
+
+    sreg = qemu_get_ubyte(f);
+    cpu_set_sreg(env, sreg);
+    return 0;
+}
+
+static void put_sreg(QEMUFile *f, void *opaque, size_t size)
+{
+    CPUAVRState *env = opaque;
+    uint8_t sreg = cpu_get_sreg(env);
+
+    qemu_put_ubyte(f, sreg);
+}
+
+static const VMStateInfo vms_sreg = {
+    .name = "sreg",
+    .get = get_sreg,
+    .put = put_sreg,
+};
+
+static int get_segment(QEMUFile *f, void *opaque, size_t size)
+{
+    uint32_t *ramp = opaque;
+    uint8_t temp;
+
+    temp = qemu_get_ubyte(f);
+    *ramp = ((uint32_t)temp) << 16;
+    return 0;
+}
+
+static void put_segment(QEMUFile *f, void *opaque, size_t size)
+{
+    uint32_t *ramp = opaque;
+    uint8_t temp = *ramp >> 16;
+
+    qemu_put_ubyte(f, temp);
+}
+
+static const VMStateInfo vms_rampD = {
+    .name = "rampD",
+    .get = get_segment,
+    .put = put_segment,
+};
+static const VMStateInfo vms_rampX = {
+    .name = "rampX",
+    .get = get_segment,
+    .put = put_segment,
+};
+static const VMStateInfo vms_rampY = {
+    .name = "rampY",
+    .get = get_segment,
+    .put = put_segment,
+};
+static const VMStateInfo vms_rampZ = {
+    .name = "rampZ",
+    .get = get_segment,
+    .put = put_segment,
+};
+static const VMStateInfo vms_eind = {
+    .name = "eind",
+    .get = get_segment,
+    .put = put_segment,
+};
+
+const VMStateDescription vms_avr_cpu = {
+    .name = "cpu",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(env.pc_w, AVRCPU),
+        VMSTATE_UINT32(env.sp, AVRCPU),
+
+        VMSTATE_UINT32_ARRAY(env.r, AVRCPU, AVR_CPU_REGS),
+
+        VMSTATE_SINGLE(env, AVRCPU, 0, vms_sreg, CPUAVRState),
+        VMSTATE_SINGLE(env.rampD, AVRCPU, 0, vms_rampD, uint32_t),
+        VMSTATE_SINGLE(env.rampX, AVRCPU, 0, vms_rampX, uint32_t),
+        VMSTATE_SINGLE(env.rampY, AVRCPU, 0, vms_rampY, uint32_t),
+        VMSTATE_SINGLE(env.rampZ, AVRCPU, 0, vms_rampZ, uint32_t),
+        VMSTATE_SINGLE(env.eind, AVRCPU, 0, vms_eind, uint32_t),
+
+        VMSTATE_END_OF_LIST()
+    }
+};
diff --git a/target-avr/translate.c b/target-avr/translate.c
new file mode 100644
index 0000000..ded7ba5
--- /dev/null
+++ b/target-avr/translate.c
@@ -0,0 +1,255 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "translate.h"
+
+TCGv_env cpu_env;
+
+TCGv cpu_pc;
+
+TCGv cpu_Cf;
+TCGv cpu_Zf;
+TCGv cpu_Nf;
+TCGv cpu_Vf;
+TCGv cpu_Sf;
+TCGv cpu_Hf;
+TCGv cpu_Tf;
+TCGv cpu_If;
+
+TCGv cpu_rampD;
+TCGv cpu_rampX;
+TCGv cpu_rampY;
+TCGv cpu_rampZ;
+
+TCGv cpu_r[32];
+TCGv cpu_eind;
+TCGv cpu_sp;
+
+#include "exec/gen-icount.h"
+#define REG(x) (cpu_r[x])
+
+void avr_translate_init(void)
+{
+    int i;
+    static int done_init;
+
+    if (done_init) {
+        return;
+    }
+#define AVR_REG_OFFS(x) offsetof(CPUAVRState, x)
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    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");
+
+    for (i = 0; i < 32; i++) {
+        char name[16];
+
+        sprintf(name, "r[%d]", i);
+
+        cpu_r[i] = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(r[i]), name);
+    }
+
+    done_init = 1;
+}
+
+static void decode_opc(AVRCPU *cpu, DisasContext *ctx, InstInfo *inst)
+{
+    CPUAVRState *env = &cpu->env;
+
+    inst->opcode = cpu_ldl_code(env, inst->cpc * 2);/* pc points to words */
+    inst->length = 16;
+    inst->translate = NULL;
+
+    if (inst->length == 16) {
+        inst->npc = inst->cpc + 1;
+        /* get opcode as 16bit value */
+        inst->opcode = inst->opcode & 0x0000ffff;
+    }
+    if (inst->length == 32) {
+        inst->npc = inst->cpc + 2;
+        /* get opcode as 32bit value */
+        inst->opcode = (inst->opcode << 16)
+                     | (inst->opcode >> 16);
+    }
+}
+
+/* generate intermediate code for basic block 'tb'. */
+void gen_intermediate_code(CPUAVRState *env, struct TranslationBlock *tb)
+{
+    AVRCPU *cpu = avr_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+    DisasContext ctx;
+    target_ulong pc_start;
+    int num_insns, max_insns;
+    target_ulong cpc;
+    target_ulong npc;
+
+    pc_start = tb->pc / 2;
+    ctx.tb = tb;
+    ctx.memidx = 0;
+    ctx.bstate = BS_NONE;
+    ctx.singlestep = cs->singlestep_enabled;
+    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);
+
+    /* decode first instruction */
+    ctx.inst[0].cpc = pc_start;
+    decode_opc(cpu, &ctx, &ctx.inst[0]);
+    do {
+        /* set curr/next PCs */
+        cpc = ctx.inst[0].cpc;
+        npc = ctx.inst[0].npc;
+
+        /* decode next instruction */
+        ctx.inst[1].cpc = ctx.inst[0].npc;
+        decode_opc(cpu, &ctx, &ctx.inst[1]);
+
+        /* translate current instruction */
+        tcg_gen_insn_start(cpc);
+        num_insns++;
+
+        /*
+         * this is due to some strange GDB behavior
+         * let's assume main is has 0x100 address
+         * b main   - sets a breakpoint to 0x00000100 address (code)
+         * b *0x100 - sets a breakpoint to 0x00800100 address (data)
+         */
+        if (unlikely(cpu_breakpoint_test(cs, PHYS_BASE_CODE + cpc * 2, BP_ANY))
+                 || cpu_breakpoint_test(cs, PHYS_BASE_DATA + cpc * 2, BP_ANY)) {
+            tcg_gen_movi_i32(cpu_pc, cpc);
+            gen_helper_debug(cpu_env);
+            ctx.bstate = BS_EXCP;
+            goto done_generating;
+        }
+
+        if (ctx.inst[0].translate) {
+            ctx.bstate = ctx.inst[0].translate(env, &ctx, ctx.inst[0].opcode);
+        }
+
+        if (num_insns >= max_insns) {
+            break; /* max translated instructions limit reached */
+        }
+        if (ctx.singlestep) {
+            break; /* single step */
+        }
+        if ((cpc & (TARGET_PAGE_SIZE - 1)) == 0) {
+            break; /* page boundary */
+        }
+
+        ctx.inst[0] = ctx.inst[1]; /* make next inst curr */
+    } while (ctx.bstate == BS_NONE && !tcg_op_buf_full());
+
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
+    if (ctx.singlestep) {
+        if (ctx.bstate == BS_STOP || ctx.bstate == BS_NONE) {
+            tcg_gen_movi_tl(cpu_pc, npc);
+        }
+        gen_helper_debug(cpu_env);
+        tcg_gen_exit_tb(0);
+    } else {
+        switch (ctx.bstate) {
+        case BS_STOP:
+        case BS_NONE:
+            gen_goto_tb(env, &ctx, 0, npc);
+            break;
+        case BS_EXCP:
+            tcg_gen_exit_tb(0);
+            break;
+        default:
+            break;
+        }
+    }
+
+done_generating:
+    gen_tb_end(tb, num_insns);
+
+    tb->size = (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];
+}
+
+void avr_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
+                            int flags)
+{
+    AVRCPU *cpu = AVR_CPU(cs);
+    CPUAVRState *env = &cpu->env;
+    int i;
+
+    cpu_fprintf(f, "\n");
+    cpu_fprintf(f, "PC:    %06x\n", env->pc_w);
+    cpu_fprintf(f, "SP:      %04x\n", env->sp);
+    cpu_fprintf(f, "rampD:     %02x\n", env->rampD >> 16);
+    cpu_fprintf(f, "rampX:     %02x\n", env->rampX >> 16);
+    cpu_fprintf(f, "rampY:     %02x\n", env->rampY >> 16);
+    cpu_fprintf(f, "rampZ:     %02x\n", env->rampZ >> 16);
+    cpu_fprintf(f, "EIND:      %02x\n", env->eind);
+    cpu_fprintf(f, "X:       %02x%02x\n", env->r[27], env->r[26]);
+    cpu_fprintf(f, "Y:       %02x%02x\n", env->r[29], env->r[28]);
+    cpu_fprintf(f, "Z:       %02x%02x\n", env->r[31], env->r[30]);
+    cpu_fprintf(f, "SREG:    [ %c %c %c %c %c %c %c %c ]\n",
+                        env->sregI ? 'I' : '-',
+                        env->sregT ? 'T' : '-',
+                        env->sregH ? 'H' : '-',
+                        env->sregS ? 'S' : '-',
+                        env->sregV ? 'V' : '-',
+                        env->sregN ? '-' : 'N', /* Zf has negative logic */
+                        env->sregZ ? 'Z' : '-',
+                        env->sregC ? 'I' : '-');
+
+    cpu_fprintf(f, "\n");
+    for (i = 0; i < ARRAY_SIZE(env->r); i++) {
+        cpu_fprintf(f, "R[%02d]:  %02x   ", i, env->r[i]);
+
+        if ((i % 8) == 7) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+    cpu_fprintf(f, "\n");
+}
diff --git a/target-avr/translate.h b/target-avr/translate.h
new file mode 100644
index 0000000..99045a3
--- /dev/null
+++ b/target-avr/translate.h
@@ -0,0 +1,114 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#ifndef AVR_TRANSLATE_H_
+#define AVR_TRANSLATE_H_
+
+#include "qemu/osdep.h"
+
+#include "tcg/tcg.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "disas/disas.h"
+#include "tcg-op.h"
+#include "exec/cpu_ldst.h"
+
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+#include "exec/log.h"
+
+extern TCGv_env cpu_env;
+
+extern TCGv cpu_pc;
+
+extern TCGv cpu_Cf;
+extern TCGv cpu_Zf;
+extern TCGv cpu_Nf;
+extern TCGv cpu_Vf;
+extern TCGv cpu_Sf;
+extern TCGv cpu_Hf;
+extern TCGv cpu_Tf;
+extern TCGv cpu_If;
+
+extern TCGv cpu_rampD;
+extern TCGv cpu_rampX;
+extern TCGv cpu_rampY;
+extern TCGv cpu_rampZ;
+
+extern TCGv cpu_r[32];
+extern TCGv cpu_eind;
+extern TCGv cpu_sp;
+
+enum {
+    BS_NONE = 0, /* Nothing special (none of the below) */
+    BS_STOP = 1, /* We want to stop translation for any reason */
+    BS_BRANCH = 2, /* A branch condition is reached */
+    BS_EXCP = 3, /* An exception condition is reached */
+};
+
+uint32_t get_opcode(uint8_t const *code, unsigned bitBase, unsigned bitSize);
+
+typedef struct DisasContext DisasContext;
+typedef struct InstInfo InstInfo;
+
+typedef int (*translate_function_t)(CPUAVRState *env, DisasContext *ctx,
+                                        uint32_t opcode);
+struct InstInfo {
+    target_long cpc;
+    target_long npc;
+    uint32_t opcode;
+    translate_function_t translate;
+    unsigned length;
+};
+
+/* This is the state at translation time. */
+struct DisasContext {
+    struct TranslationBlock *tb;
+
+    InstInfo inst[2];/* two consecutive instructions */
+
+    /* Routine used to access memory */
+    int memidx;
+    int bstate;
+    int singlestep;
+};
+
+void avr_decode(uint32_t pc, uint32_t *length, uint32_t opcode,
+                        translate_function_t *translate);
+
+static inline void gen_goto_tb(CPUAVRState *env, DisasContext *ctx,
+                        int n, target_ulong dest)
+{
+    TranslationBlock *tb;
+
+    tb = ctx->tb;
+
+    if (ctx->singlestep == 0) {
+        tcg_gen_goto_tb(n);
+        tcg_gen_movi_i32(cpu_pc, dest);
+        tcg_gen_exit_tb((uintptr_t)tb + n);
+    } else {
+        tcg_gen_movi_i32(cpu_pc, dest);
+        gen_helper_debug(cpu_env);
+        tcg_gen_exit_tb(0);
+    }
+}
+
+#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 02/13] target-avr: adding AVR CPU features/flavors
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 01/13] target-avr: AVR cores support is added Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 03/13] target-avr: adding a sample AVR board Richard Henderson
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-3-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/cpu.c | 311 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 target-avr/cpu.h |  48 +++++++++
 2 files changed, 359 insertions(+)

diff --git a/target-avr/cpu.c b/target-avr/cpu.c
index ed2b1b8..cf66197 100644
--- a/target-avr/cpu.c
+++ b/target-avr/cpu.c
@@ -200,12 +200,323 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
     dc->cannot_destroy_with_object_finalize_yet = true;
 }
 
+static void avr_avr1_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+}
+
+static void avr_avr2_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+}
+
+static void avr_avr25_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+}
+
+static void avr_avr3_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+}
+
+static void avr_avr31_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+}
+
+static void avr_avr35_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+}
+
+static void avr_avr4_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+}
+
+static void avr_avr5_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+}
+
+static void avr_avr51_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+}
+
+static void avr_avr6_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_3_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_EIJMP_EICALL);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+}
+
+static void avr_xmega2_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
+static void avr_xmega4_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
+static void avr_xmega5_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPD);
+    avr_set_feature(env, AVR_FEATURE_RAMPX);
+    avr_set_feature(env, AVR_FEATURE_RAMPY);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
+static void avr_xmega6_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_3_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_EIJMP_EICALL);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
+static void avr_xmega7_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_3_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPD);
+    avr_set_feature(env, AVR_FEATURE_RAMPX);
+    avr_set_feature(env, AVR_FEATURE_RAMPY);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_EIJMP_EICALL);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
 typedef struct AVRCPUInfo {
     const char *name;
     void (*initfn)(Object *obj);
 } AVRCPUInfo;
 
 static const AVRCPUInfo avr_cpus[] = {
+    {.name = "avr1", .initfn = avr_avr1_initfn},
+    {.name = "avr2", .initfn = avr_avr2_initfn},
+    {.name = "avr25", .initfn = avr_avr25_initfn},
+    {.name = "avr3", .initfn = avr_avr3_initfn},
+    {.name = "avr31", .initfn = avr_avr31_initfn},
+    {.name = "avr35", .initfn = avr_avr35_initfn},
+    {.name = "avr4", .initfn = avr_avr4_initfn},
+    {.name = "avr5", .initfn = avr_avr5_initfn},
+    {.name = "avr51", .initfn = avr_avr51_initfn},
+    {.name = "avr6", .initfn = avr_avr6_initfn},
+    {.name = "xmega2", .initfn = avr_xmega2_initfn},
+    {.name = "xmega4", .initfn = avr_xmega4_initfn},
+    {.name = "xmega5", .initfn = avr_xmega5_initfn},
+    {.name = "xmega6", .initfn = avr_xmega6_initfn},
+    {.name = "xmega7", .initfn = avr_xmega7_initfn},
 };
 
 static gint avr_cpu_list_compare(gconstpointer a, gconstpointer b)
diff --git a/target-avr/cpu.h b/target-avr/cpu.h
index fb05216..54dc58c 100644
--- a/target-avr/cpu.h
+++ b/target-avr/cpu.h
@@ -78,6 +78,42 @@
 #define AVR_CPU_REGS_LAST (AVR_CPU_REGS_BASE + AVR_CPU_REGS - 1)
 #define AVR_CPU_IO_REGS_LAST (AVR_CPU_IO_REGS_BASE + AVR_CPU_IO_REGS - 1)
 
+enum avr_features {
+    AVR_FEATURE_SRAM,
+
+    AVR_FEATURE_1_BYTE_PC,
+    AVR_FEATURE_2_BYTE_PC,
+    AVR_FEATURE_3_BYTE_PC,
+
+    AVR_FEATURE_1_BYTE_SP,
+    AVR_FEATURE_2_BYTE_SP,
+
+    AVR_FEATURE_BREAK,
+    AVR_FEATURE_DES,
+    AVR_FEATURE_RMW, /* Read Modify Write - XCH LAC LAS LAT */
+
+    AVR_FEATURE_EIJMP_EICALL,
+    AVR_FEATURE_IJMP_ICALL,
+    AVR_FEATURE_JMP_CALL,
+
+    AVR_FEATURE_ADIW_SBIW,
+
+    AVR_FEATURE_SPM,
+    AVR_FEATURE_SPMX,
+
+    AVR_FEATURE_ELPMX,
+    AVR_FEATURE_ELPM,
+    AVR_FEATURE_LPMX,
+    AVR_FEATURE_LPM,
+
+    AVR_FEATURE_MOVW,
+    AVR_FEATURE_MUL,
+    AVR_FEATURE_RAMPD,
+    AVR_FEATURE_RAMPX,
+    AVR_FEATURE_RAMPY,
+    AVR_FEATURE_RAMPZ,
+};
+
 typedef struct CPUAVRState CPUAVRState;
 
 struct CPUAVRState {
@@ -104,10 +140,22 @@ struct CPUAVRState {
 
     uint64_t intsrc; /* interrupt sources */
 
+    uint32_t features;
+
     /* Those resources are used only in QEMU core */
     CPU_COMMON
 };
 
+static inline int avr_feature(CPUAVRState *env, int feature)
+{
+    return (env->features & (1U << feature)) != 0;
+}
+
+static inline void avr_set_feature(CPUAVRState *env, int feature)
+{
+    env->features |= (1U << feature);
+}
+
 #define cpu_list avr_cpu_list
 #define cpu_signal_handler cpu_avr_signal_handler
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 03/13] target-avr: adding a sample AVR board
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 01/13] target-avr: AVR cores support is added Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 02/13] target-avr: adding AVR CPU features/flavors Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 04/13] target-avr: adding instructions encodings Richard Henderson
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-4-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 MAINTAINERS          |   1 +
 hw/avr/Makefile.objs |  21 ++++++++++
 hw/avr/sample.c      | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+)
 create mode 100644 hw/avr/Makefile.objs
 create mode 100644 hw/avr/sample.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e526316..3f36b06 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -115,6 +115,7 @@ AVR
 M: Michael Rolnik <mrolnik@gmail.com>
 S: Maintained
 F: target-avr/
+F: hw/avr/
 
 CRIS
 M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
new file mode 100644
index 0000000..8f537c9
--- /dev/null
+++ b/hw/avr/Makefile.objs
@@ -0,0 +1,21 @@
+#
+#  QEMU AVR CPU
+#
+#  Copyright (c) 2016 Michael Rolnik
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, see
+#  <http://www.gnu.org/licenses/lgpl-2.1.html>
+#
+
+obj-y += sample.o
diff --git a/hw/avr/sample.c b/hw/avr/sample.c
new file mode 100644
index 0000000..6d15646
--- /dev/null
+++ b/hw/avr/sample.c
@@ -0,0 +1,111 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+/*
+ *  NOTE:
+ *      This is not a real AVR board !!! This is an example !!!
+ *
+ *        This example can be used to build a real AVR board.
+ *
+ *      This example board loads provided binary file into flash memory and
+ *      executes it from 0x00000000 address in the code memory space.
+ *
+ *      Currently used for AVR CPU validation
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
+#include "ui/console.h"
+#include "hw/boards.h"
+#include "hw/devices.h"
+#include "hw/loader.h"
+#include "qemu/error-report.h"
+#include "exec/address-spaces.h"
+#include "include/hw/sysbus.h"
+
+#define VIRT_BASE_FLASH 0x00000000
+#define VIRT_BASE_ISRAM 0x00000100
+#define VIRT_BASE_EXMEM 0x00001100
+#define VIRT_BASE_EEPROM 0x00000000
+
+#define SIZE_FLASH 0x00020000
+#define SIZE_ISRAM 0x00001000
+#define SIZE_EXMEM 0x00010000
+#define SIZE_EEPROM 0x00001000
+#define SIZE_IOREG SIZE_REGS
+
+#define PHYS_BASE_FLASH (PHYS_BASE_CODE)
+
+#define PHYS_BASE_ISRAM (PHYS_BASE_DATA)
+#define PHYS_BASE_EXMEM (PHYS_BASE_ISRAM + SIZE_ISRAM)
+#define PHYS_BASE_EEPROM (PHYS_BASE_EXMEM + SIZE_EXMEM)
+
+#define PHYS_BASE_IOREG (PHYS_BASE_REGS + 0x20)
+
+static void sample_init(MachineState *machine)
+{
+    MemoryRegion *address_space_mem;
+    MemoryRegion *ram;
+    MemoryRegion *flash;
+    unsigned ram_size = SIZE_ISRAM + SIZE_EXMEM;
+    AVRCPU *cpu_avr ATTRIBUTE_UNUSED;
+    const char *firmware = NULL;
+    const char *filename;
+
+    address_space_mem = get_system_memory();
+    ram = g_new(MemoryRegion, 1);
+    flash = g_new(MemoryRegion, 1);
+
+    cpu_avr = cpu_avr_init("avr5");
+
+    memory_region_allocate_system_memory(ram, NULL, "avr.ram", ram_size);
+    memory_region_add_subregion(address_space_mem, PHYS_BASE_ISRAM, ram);
+
+    memory_region_init_rom(flash, NULL, "avr.flash", SIZE_FLASH, &error_fatal);
+    memory_region_add_subregion(address_space_mem, PHYS_BASE_FLASH, flash);
+    vmstate_register_ram_global(flash);
+
+    if (machine->firmware) {
+        firmware = machine->firmware;
+    }
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
+    if (!filename) {
+        error_report("Could not find flash image file '%s'", firmware);
+        exit(1);
+    }
+
+    load_image_targphys(filename, PHYS_BASE_FLASH, SIZE_FLASH);
+}
+
+static void sample_machine_init(MachineClass *mc)
+{
+    mc->desc = "AVR sample/example board";
+    mc->init = sample_init;
+    mc->is_default = 1;
+}
+
+DEFINE_MACHINE("sample", sample_machine_init)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 04/13] target-avr: adding instructions encodings
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (2 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 03/13] target-avr: adding a sample AVR board Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 05/13] target-avr: adding AVR interrupt handling Richard Henderson
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-5-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/translate-inst.h | 804 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 804 insertions(+)
 create mode 100644 target-avr/translate-inst.h

diff --git a/target-avr/translate-inst.h b/target-avr/translate-inst.h
new file mode 100644
index 0000000..af2e076
--- /dev/null
+++ b/target-avr/translate-inst.h
@@ -0,0 +1,804 @@
+/*
+ *  QEMU AVR CPU
+ *
+ *  Copyright (c) 2016 Michael Rolnik
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, see
+ *  <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#ifndef AVR_TRANSLATE_INST_H_
+#define AVR_TRANSLATE_INST_H_
+
+typedef struct DisasContext DisasContext;
+
+int avr_translate_NOP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_MOVW(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t MOVW_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 0, 4);
+}
+
+static inline uint32_t MOVW_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+int avr_translate_MULS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t MULS_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 0, 4);
+}
+
+static inline uint32_t MULS_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+int avr_translate_MULSU(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t MULSU_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t MULSU_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 3);
+}
+
+int avr_translate_FMUL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t FMUL_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t FMUL_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 3);
+}
+
+int avr_translate_FMULS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t FMULS_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t FMULS_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 3);
+}
+
+int avr_translate_FMULSU(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t FMULSU_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t FMULSU_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 3);
+}
+
+int avr_translate_CPC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t CPC_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t CPC_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_SBC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SBC_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t SBC_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_ADD(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ADD_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t ADD_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_AND(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t AND_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t AND_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_EOR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t EOR_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t EOR_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_OR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t OR_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t OR_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_MOV(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t MOV_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t MOV_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_CPSE(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t CPSE_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t CPSE_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_CP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t CP_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t CP_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_SUB(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SUB_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t SUB_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_ADC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ADC_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t ADC_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_CPI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t CPI_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+static inline uint32_t CPI_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 8, 4) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_SBCI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SBCI_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+static inline uint32_t SBCI_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 8, 4) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_ORI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ORI_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+static inline uint32_t ORI_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 8, 4) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_SUBI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SUBI_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+static inline uint32_t SUBI_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 8, 4) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_ANDI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ANDI_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+static inline uint32_t ANDI_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 8, 4) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_LDDZ(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDDZ_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t LDDZ_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 13, 1) << 5) |
+            (extract32(opcode, 10, 2) << 3) |
+            (extract32(opcode, 0, 3));
+}
+
+int avr_translate_LDDY(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDDY_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t LDDY_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 13, 1) << 5) |
+            (extract32(opcode, 10, 2) << 3) |
+            (extract32(opcode, 0, 3));
+}
+
+int avr_translate_STDZ(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STDZ_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t STDZ_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 13, 1) << 5) |
+            (extract32(opcode, 10, 2) << 3) |
+            (extract32(opcode, 0, 3));
+}
+
+int avr_translate_STDY(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STDY_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t STDY_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 13, 1) << 5) |
+            (extract32(opcode, 10, 2) << 3) |
+            (extract32(opcode, 0, 3));
+}
+
+int avr_translate_LDS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDS_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 0, 16);
+}
+
+static inline uint32_t LDS_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 20, 5);
+}
+
+int avr_translate_LDZ2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDZ2_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LDZ3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDZ3_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LPM2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LPM2_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LPMX(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LPMX_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_ELPM2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ELPM2_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_ELPMX(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ELPMX_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LDY2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDY2_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LDY3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDY3_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LDX1(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDX1_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LDX2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDX2_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LDX3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDX3_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_POP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t POP_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_STS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STS_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 0, 16);
+}
+
+static inline uint32_t STS_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 20, 5);
+}
+
+int avr_translate_STZ2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STZ2_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_STZ3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STZ3_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_XCH(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t XCH_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LAS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LAS_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LAC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LAC_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LAT(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LAT_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_STY2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STY2_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_STY3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STY3_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_STX1(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STX1_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_STX2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STX2_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_STX3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t STX3_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_PUSH(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t PUSH_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_COM(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t COM_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_NEG(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t NEG_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_SWAP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SWAP_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_INC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t INC_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_ASR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ASR_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_LSR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LSR_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_ROR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ROR_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_BSET(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t BSET_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 4, 3);
+}
+
+int avr_translate_IJMP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_EIJMP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_BCLR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t BCLR_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 4, 3);
+}
+
+int avr_translate_RET(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_RETI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_ICALL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_EICALL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_SLEEP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_BREAK(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_WDR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_LPM1(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_ELPM1(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_SPM(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_SPMX(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+
+int avr_translate_DEC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t DEC_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_DES(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t DES_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+int avr_translate_JMP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t JMP_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 20, 5) << 17) |
+            (extract32(opcode, 0, 17));
+}
+
+int avr_translate_CALL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t CALL_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 20, 5) << 17) |
+            (extract32(opcode, 0, 17));
+}
+
+int avr_translate_ADIW(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t ADIW_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 2);
+}
+
+static inline uint32_t ADIW_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 6, 2) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_SBIW(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SBIW_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 2);
+}
+
+static inline uint32_t SBIW_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 6, 2) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_CBI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t CBI_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t CBI_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 3, 5);
+}
+
+int avr_translate_SBIC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SBIC_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t SBIC_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 3, 5);
+}
+
+int avr_translate_SBI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SBI_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t SBI_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 3, 5);
+}
+
+int avr_translate_SBIS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SBIS_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t SBIS_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 3, 5);
+}
+
+int avr_translate_MUL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t MUL_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t MUL_Rr(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 1) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_IN(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t IN_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t IN_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 2) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_OUT(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t OUT_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+static inline uint32_t OUT_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 9, 2) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_RJMP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t RJMP_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 0, 12);
+}
+
+int avr_translate_LDI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t LDI_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 4);
+}
+
+static inline uint32_t LDI_Imm(uint32_t opcode)
+{
+    return (extract32(opcode, 8, 4) << 4) |
+            (extract32(opcode, 0, 4));
+}
+
+int avr_translate_RCALL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t RCALL_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 0, 12);
+}
+
+int avr_translate_BRBS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t BRBS_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t BRBS_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 3, 7);
+}
+
+int avr_translate_BRBC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t BRBC_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t BRBC_Imm(uint32_t opcode)
+{
+    return extract32(opcode, 3, 7);
+}
+
+int avr_translate_BLD(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t BLD_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t BLD_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_BST(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t BST_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t BST_Rd(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_SBRC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SBRC_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t SBRC_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+int avr_translate_SBRS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+static inline uint32_t SBRS_Bit(uint32_t opcode)
+{
+    return extract32(opcode, 0, 3);
+}
+
+static inline uint32_t SBRS_Rr(uint32_t opcode)
+{
+    return extract32(opcode, 4, 5);
+}
+
+#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 05/13] target-avr: adding AVR interrupt handling
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (3 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 04/13] target-avr: adding instructions encodings Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 06/13] target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions Richard Henderson
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-6-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/helper.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/target-avr/helper.c b/target-avr/helper.c
index c187193..61255fd 100644
--- a/target-avr/helper.c
+++ b/target-avr/helper.c
@@ -32,11 +32,66 @@
 bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
     bool ret = false;
+    CPUClass *cc = CPU_GET_CLASS(cs);
+    AVRCPU *cpu = AVR_CPU(cs);
+    CPUAVRState *env = &cpu->env;
+
+    if (interrupt_request & CPU_INTERRUPT_RESET) {
+        if (cpu_interrupts_enabled(env)) {
+            cs->exception_index = EXCP_RESET;
+            cc->do_interrupt(cs);
+
+            cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
+
+            ret = true;
+        }
+    }
+    if (interrupt_request & CPU_INTERRUPT_HARD) {
+        if (cpu_interrupts_enabled(env) && env->intsrc != 0) {
+            int index = ctz32(env->intsrc);
+            cs->exception_index = EXCP_INT(index);
+            cc->do_interrupt(cs);
+
+            env->intsrc &= env->intsrc - 1; /* clear the interrupt */
+            cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
+
+            ret = true;
+        }
+    }
     return ret;
 }
 
 void avr_cpu_do_interrupt(CPUState *cs)
 {
+    AVRCPU *cpu = AVR_CPU(cs);
+    CPUAVRState *env = &cpu->env;
+
+    uint32_t ret = env->pc_w;
+    int vector = 0;
+    int size = avr_feature(env, AVR_FEATURE_JMP_CALL) ? 2 : 1;
+    int base = 0; /* TODO: where to get it */
+
+    if (cs->exception_index == EXCP_RESET) {
+        vector = 0;
+    } else if (env->intsrc != 0) {
+        vector = ctz32(env->intsrc) + 1;
+    }
+
+    if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+        cpu_stb_data(env, env->sp--, (ret & 0x0000ff));
+        cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >>  8);
+        cpu_stb_data(env, env->sp--, (ret & 0xff0000) >> 16);
+    } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) {
+        cpu_stb_data(env, env->sp--, (ret & 0x0000ff));
+        cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >>  8);
+    } else {
+        cpu_stb_data(env, env->sp--, (ret & 0x0000ff));
+    }
+
+    env->pc_w = base + vector * size;
+    env->sregI = 0; /* clear Global Interrupt Flag */
+
+    cs->exception_index = -1;
 }
 
 int avr_cpu_memory_rw_debug(CPUState *cs, vaddr addr, uint8_t *buf,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 06/13] target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (4 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 05/13] target-avr: adding AVR interrupt handling Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 07/13] target-avr: adding instruction translation Richard Henderson
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-7-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/cpu.h       |  10 +++
 target-avr/helper.c    | 216 ++++++++++++++++++++++++++++++++++++++++++++++++-
 target-avr/helper.h    |   7 ++
 target-avr/translate.c |   8 ++
 4 files changed, 239 insertions(+), 2 deletions(-)

diff --git a/target-avr/cpu.h b/target-avr/cpu.h
index 54dc58c..9214324 100644
--- a/target-avr/cpu.h
+++ b/target-avr/cpu.h
@@ -139,6 +139,7 @@ struct CPUAVRState {
     uint32_t sp; /* 16 bits */
 
     uint64_t intsrc; /* interrupt sources */
+    bool fullacc;/* CPU/MEM if true MEM only otherwise */
 
     uint32_t features;
 
@@ -181,6 +182,10 @@ int avr_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 int avr_cpu_memory_rw_debug(CPUState *cs, vaddr address, uint8_t *buf,
                                 int len, bool is_write);
 
+enum {
+    TB_FLAGS_FULL_ACCESS = 1,
+};
+
 static inline void cpu_get_tb_cpu_state(CPUAVRState *env, target_ulong *pc,
                                 target_ulong *cs_base, uint32_t *pflags)
 {
@@ -188,6 +193,11 @@ static inline void cpu_get_tb_cpu_state(CPUAVRState *env, target_ulong *pc,
 
     *pc = env->pc_w * 2;
     *cs_base = 0;
+
+    if (env->fullacc) {
+        flags |= TB_FLAGS_FULL_ACCESS;
+    }
+
     *pflags = flags;
 }
 
diff --git a/target-avr/helper.c b/target-avr/helper.c
index 61255fd..bc53053 100644
--- a/target-avr/helper.c
+++ b/target-avr/helper.c
@@ -28,6 +28,7 @@
 #include "exec/cpu_ldst.h"
 #include "qemu/host-utils.h"
 #include "exec/helper-proto.h"
+#include "exec/ioport.h"
 
 bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
@@ -79,11 +80,11 @@ void avr_cpu_do_interrupt(CPUState *cs)
 
     if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
         cpu_stb_data(env, env->sp--, (ret & 0x0000ff));
-        cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >>  8);
+        cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >> 8);
         cpu_stb_data(env, env->sp--, (ret & 0xff0000) >> 16);
     } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) {
         cpu_stb_data(env, env->sp--, (ret & 0x0000ff));
-        cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >>  8);
+        cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >> 8);
     } else {
         cpu_stb_data(env, env->sp--, (ret & 0x0000ff));
     }
@@ -126,7 +127,19 @@ void tlb_fill(CPUState *cs, target_ulong vaddr, MMUAccessType access_type,
     if (mmu_idx == MMU_CODE_IDX) {
         paddr = PHYS_BASE_CODE + vaddr - VIRT_BASE_CODE;
         prot = PAGE_READ | PAGE_EXEC;
+    } else if (vaddr - VIRT_BASE_REGS < AVR_REGS) {
+        /*
+         * this is a write into CPU registers, exit and rebuilt this TB
+         * to use full write
+         */
+        AVRCPU *cpu = AVR_CPU(cs);
+        CPUAVRState *env = &cpu->env;
+        env->fullacc = 1;
+        cpu_loop_exit_restore(cs, retaddr);
     } else {
+        /*
+         * this is a write into memory. nothing special
+         */
         paddr = PHYS_BASE_DATA + vaddr - VIRT_BASE_DATA;
         prot = PAGE_READ | PAGE_WRITE;
     }
@@ -134,6 +147,30 @@ void tlb_fill(CPUState *cs, target_ulong vaddr, MMUAccessType access_type,
     tlb_set_page_with_attrs(cs, vaddr, paddr, attrs, prot, mmu_idx, page_size);
 }
 
+void helper_sleep(CPUAVRState *env)
+{
+    CPUState *cs = CPU(avr_env_get_cpu(env));
+
+    cs->exception_index = EXCP_HLT;
+    cpu_loop_exit(cs);
+}
+
+void helper_unsupported(CPUAVRState *env)
+{
+    CPUState *cs = CPU(avr_env_get_cpu(env));
+
+    /*
+     *  I count not find what happens on the real platform, so
+     *  it's EXCP_DEBUG for meanwhile
+     */
+    cs->exception_index = EXCP_DEBUG;
+    if (qemu_loglevel_mask(LOG_UNIMP)) {
+        qemu_log("UNSUPPORTED\n");
+        cpu_dump_state(cs, qemu_logfile, fprintf, 0);
+    }
+    cpu_loop_exit(cs);
+}
+
 void helper_debug(CPUAVRState *env)
 {
     CPUState *cs = CPU(avr_env_get_cpu(env));
@@ -141,3 +178,178 @@ void helper_debug(CPUAVRState *env)
     cs->exception_index = EXCP_DEBUG;
     cpu_loop_exit(cs);
 }
+
+void helper_wdr(CPUAVRState *env)
+{
+    CPUState *cs = CPU(avr_env_get_cpu(env));
+
+    /* WD is not implemented yet, placeholder */
+    cs->exception_index = EXCP_DEBUG;
+    cpu_loop_exit(cs);
+}
+
+/*
+ * This function implements IN instruction
+ *
+ * It does the following
+ * a.  if an IO register belongs to CPU, its value is read and returned
+ * b.  otherwise io address is translated to mem address and physical memory
+ *     is read.
+ * c.  it caches the value for sake of SBI, SBIC, SBIS & CBI implementation
+ *
+ */
+target_ulong helper_inb(CPUAVRState *env, uint32_t port)
+{
+    target_ulong data = 0;
+
+    switch (port) {
+    case 0x38: /* RAMPD */
+        data = 0xff & (env->rampD >> 16);
+        break;
+    case 0x39: /* RAMPX */
+        data = 0xff & (env->rampX >> 16);
+        break;
+    case 0x3a: /* RAMPY */
+        data = 0xff & (env->rampY >> 16);
+        break;
+    case 0x3b: /* RAMPZ */
+        data = 0xff & (env->rampZ >> 16);
+        break;
+    case 0x3c: /* EIND */
+        data = 0xff & (env->eind >> 16);
+        break;
+    case 0x3d: /* SPL */
+        data = env->sp & 0x00ff;
+        break;
+    case 0x3e: /* SPH */
+        data = env->sp >> 8;
+        break;
+    case 0x3f: /* SREG */
+        data = cpu_get_sreg(env);
+        break;
+    default:
+        /*
+         * CPU does not know how to read this register, pass it to the
+         * device/board
+         */
+        cpu_physical_memory_read(PHYS_BASE_REGS + port + AVR_CPU_IO_REGS_BASE,
+                                 &data, 1);
+    }
+
+    return data;
+}
+
+/*
+ *  This function implements OUT instruction
+ *
+ *  It does the following
+ *  a.  if an IO register belongs to CPU, its value is written into the register
+ *  b.  otherwise io address is translated to mem address and physical memory
+ *      is written.
+ *  c.  it caches the value for sake of SBI, SBIC, SBIS & CBI implementation
+ *
+ */
+void helper_outb(CPUAVRState *env, uint32_t port, uint32_t data)
+{
+    data &= 0x000000ff;
+
+    switch (port) {
+    case 0x04:
+        {
+            CPUState *cpu = CPU(avr_env_get_cpu(env));
+            qemu_irq irq = qdev_get_gpio_in(DEVICE(cpu), 3);
+            qemu_set_irq(irq, 1);
+        }
+        break;
+    case 0x38: /* RAMPD */
+        if (avr_feature(env, AVR_FEATURE_RAMPD)) {
+            env->rampD = (data & 0xff) << 16;
+        }
+        break;
+    case 0x39: /* RAMPX */
+        if (avr_feature(env, AVR_FEATURE_RAMPX)) {
+            env->rampX = (data & 0xff) << 16;
+        }
+        break;
+    case 0x3a: /* RAMPY */
+        if (avr_feature(env, AVR_FEATURE_RAMPY)) {
+            env->rampY = (data & 0xff) << 16;
+        }
+        break;
+    case 0x3b: /* RAMPZ */
+        if (avr_feature(env, AVR_FEATURE_RAMPZ)) {
+            env->rampZ = (data & 0xff) << 16;
+        }
+        break;
+    case 0x3c: /* EIDN */
+        env->eind = (data & 0xff) << 16;
+        break;
+    case 0x3d: /* SPL */
+        env->sp = (env->sp & 0xff00) | (data);
+        break;
+    case 0x3e: /* SPH */
+        if (avr_feature(env, AVR_FEATURE_2_BYTE_SP)) {
+            env->sp = (env->sp & 0x00ff) | (data << 8);
+        }
+        break;
+    case 0x3f: /* SREG */
+        cpu_set_sreg(env, data);
+        break;
+    default:
+        /*
+         * CPU does not know how to write this register, pass it to the
+         * device/board
+         */
+        cpu_physical_memory_write(PHYS_BASE_REGS + port + AVR_CPU_IO_REGS_BASE,
+                                  &data, 1);
+    }
+}
+
+/*
+ *  this function implements LD instruction when there is a posibility to read
+ *  from a CPU register
+ */
+target_ulong helper_fullrd(CPUAVRState *env, uint32_t addr)
+{
+    uint8_t data;
+
+    env->fullacc = false;
+    switch (addr) {
+    case AVR_CPU_REGS_BASE ... AVR_CPU_REGS_LAST:
+        /* CPU registers */
+        data = env->r[addr - AVR_CPU_REGS_BASE];
+        break;
+    case AVR_CPU_IO_REGS_BASE ... AVR_CPU_IO_REGS_LAST:
+        /* CPU IO registers */
+        data = helper_inb(env, addr);
+        break;
+    default:
+        /* memory */
+        cpu_physical_memory_read(PHYS_BASE_DATA + addr - VIRT_BASE_DATA,
+                                 &data, 1);
+    }
+    return data;
+}
+
+/*
+ *  this function implements LD instruction when there is a posibility to write
+ *  into a CPU register
+ */
+void helper_fullwr(CPUAVRState *env, uint32_t data, uint32_t addr)
+{
+    env->fullacc = false;
+    switch (addr) {
+    case AVR_CPU_REGS_BASE ... AVR_CPU_REGS_LAST:
+        /* CPU registers */
+        env->r[addr - AVR_CPU_REGS_BASE] = data;
+        break;
+    case AVR_CPU_IO_REGS_BASE ... AVR_CPU_IO_REGS_LAST:
+        /* CPU IO registers */
+        helper_outb(env, data, addr);
+        break;
+    default:
+        /* memory */
+        cpu_physical_memory_write(PHYS_BASE_DATA + addr - VIRT_BASE_DATA,
+                                  &data, 1);
+    }
+}
diff --git a/target-avr/helper.h b/target-avr/helper.h
index b5ef3bf..6036315 100644
--- a/target-avr/helper.h
+++ b/target-avr/helper.h
@@ -18,4 +18,11 @@
  * <http://www.gnu.org/licenses/lgpl-2.1.html>
  */
 
+DEF_HELPER_1(wdr, void, env)
 DEF_HELPER_1(debug, void, env)
+DEF_HELPER_1(sleep, void, env)
+DEF_HELPER_1(unsupported, void, env)
+DEF_HELPER_3(outb, void, env, i32, i32)
+DEF_HELPER_2(inb, tl, env, i32)
+DEF_HELPER_3(fullwr, void, env, i32, i32)
+DEF_HELPER_2(fullrd, tl, env, i32)
diff --git a/target-avr/translate.c b/target-avr/translate.c
index ded7ba5..ec79ab0 100644
--- a/target-avr/translate.c
+++ b/target-avr/translate.c
@@ -128,6 +128,14 @@ void gen_intermediate_code(CPUAVRState *env, struct TranslationBlock *tb)
     if (max_insns > TCG_MAX_INSNS) {
         max_insns = TCG_MAX_INSNS;
     }
+    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;
+    }
 
     gen_tb_start(tb);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 07/13] target-avr: adding instruction translation
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (5 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 06/13] target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 08/13] target-avr: instruction decoder generator Richard Henderson
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-8-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/Makefile.objs    |    1 +
 target-avr/translate-inst.c | 2608 +++++++++++++++++++++++++++++++++++++++++++
 target-avr/translate.h      |    1 +
 3 files changed, 2610 insertions(+)
 create mode 100644 target-avr/translate-inst.c

diff --git a/target-avr/Makefile.objs b/target-avr/Makefile.objs
index 48233ef..a448792 100644
--- a/target-avr/Makefile.objs
+++ b/target-avr/Makefile.objs
@@ -20,4 +20,5 @@
 
 obj-y += translate.o cpu.o helper.o
 obj-y += gdbstub.o
+obj-y += translate-inst.o
 obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-avr/translate-inst.c b/target-avr/translate-inst.c
new file mode 100644
index 0000000..6ed98bb
--- /dev/null
+++ b/target-avr/translate-inst.c
@@ -0,0 +1,2608 @@
+/*
+ *  QEMU AVR CPU
+ *
+ *  Copyright (c) 2016 Michael Rolnik
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, see
+ *  <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "translate.h"
+#include "translate-inst.h"
+#include "qemu/bitops.h"
+
+static void gen_add_CHf(TCGv R, TCGv Rd, TCGv Rr)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv t3 = tcg_temp_new_i32();
+
+    tcg_gen_and_tl(t1, Rd, Rr); /* t1 = Rd & Rr */
+    tcg_gen_andc_tl(t2, Rd, R); /* t2 = Rd & ~R */
+    tcg_gen_andc_tl(t3, Rr, R); /* t3 = Rr & ~R */
+    tcg_gen_or_tl(t1, t1, t2); /* t1 = t1 | t2 | t3 */
+    tcg_gen_or_tl(t1, t1, t3);
+
+    tcg_gen_shri_tl(cpu_Cf, t1, 7); /* Cf = t1(7) */
+    tcg_gen_shri_tl(cpu_Hf, t1, 3); /* Hf = t1(3) */
+    tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_add_Vf(TCGv R, TCGv Rd, TCGv Rr)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+        /* t1 = Rd & Rr & ~R | ~Rd & ~Rr & R = (Rd ^ R) & ~(Rd ^ Rr) */
+    tcg_gen_xor_tl(t1, Rd, R);
+    tcg_gen_xor_tl(t2, Rd, Rr);
+    tcg_gen_andc_tl(t1, t1, t2);
+
+    tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_sub_CHf(TCGv R, TCGv Rd, TCGv Rr)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv t3 = tcg_temp_new_i32();
+
+    /* Cf & Hf */
+    tcg_gen_not_tl(t1, Rd); /* t1 = ~Rd */
+    tcg_gen_and_tl(t2, t1, Rr); /* t2 = ~Rd & Rr */
+    tcg_gen_or_tl(t3, t1, Rr); /* t3 = (~Rd | Rr) & R */
+    tcg_gen_and_tl(t3, t3, R);
+    tcg_gen_or_tl(t2, t2, t3); /* t2 = ~Rd & Rr | ~Rd & R | R & Rr */
+    tcg_gen_shri_tl(cpu_Cf, t2, 7); /* Cf = t2(7) */
+    tcg_gen_shri_tl(cpu_Hf, t2, 3); /* Hf = t2(3) */
+    tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_sub_Vf(TCGv R, TCGv Rd, TCGv Rr)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /* Vf */
+        /* t1 = Rd & ~Rr & ~R | ~Rd & Rr & R = (Rd ^ R) & (Rd ^ R) */
+    tcg_gen_xor_tl(t1, Rd, R);
+    tcg_gen_xor_tl(t2, Rd, Rr);
+    tcg_gen_and_tl(t1, t1, t2);
+    tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_NSf(TCGv R)
+{
+    tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
+    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+}
+
+static void gen_ZNSf(TCGv R)
+{
+    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+    tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
+    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+}
+
+static void gen_push_ret(CPUAVRState *env, int ret)
+{
+    if (avr_feature(env, AVR_FEATURE_1_BYTE_PC)) {
+
+        TCGv t0 = tcg_const_i32((ret & 0x0000ff));
+
+        tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_UB);
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+        tcg_temp_free_i32(t0);
+    } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) {
+
+        TCGv t0 = tcg_const_i32((ret & 0x00ffff));
+
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+        tcg_temp_free_i32(t0);
+
+    } else if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+
+        TCGv lo = tcg_const_i32((ret & 0x0000ff));
+        TCGv hi = tcg_const_i32((ret & 0xffff00) >> 8);
+
+        tcg_gen_qemu_st_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 2);
+        tcg_gen_qemu_st_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+        tcg_temp_free_i32(lo);
+        tcg_temp_free_i32(hi);
+    }
+}
+
+static void gen_pop_ret(CPUAVRState *env, TCGv ret)
+{
+    if (avr_feature(env, AVR_FEATURE_1_BYTE_PC)) {
+
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_UB);
+
+    } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) {
+
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+
+    } else if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+
+        TCGv lo = tcg_temp_new_i32();
+        TCGv hi = tcg_temp_new_i32();
+
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_ld_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 2);
+        tcg_gen_qemu_ld_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
+
+        tcg_gen_deposit_tl(ret, lo, hi, 8, 16);
+
+        tcg_temp_free_i32(lo);
+        tcg_temp_free_i32(hi);
+    }
+}
+
+static void gen_jmp_ez(void)
+{
+    tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
+    tcg_gen_or_tl(cpu_pc, cpu_pc, cpu_eind);
+    tcg_gen_exit_tb(0);
+}
+
+static void gen_jmp_z(void)
+{
+    tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
+    tcg_gen_exit_tb(0);
+}
+
+/*
+ *  in the gen_set_addr & gen_get_addr functions
+ *  H assumed to be in 0x00ff0000 format
+ *  M assumed to be in 0x000000ff format
+ *  L assumed to be in 0x000000ff format
+ */
+static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L)
+{
+
+    tcg_gen_andi_tl(L, addr, 0x000000ff);
+
+    tcg_gen_andi_tl(M, addr, 0x0000ff00);
+    tcg_gen_shri_tl(M, M, 8);
+
+    tcg_gen_andi_tl(H, addr, 0x00ff0000);
+}
+
+static void gen_set_xaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampX, cpu_r[27], cpu_r[26]);
+}
+
+static void gen_set_yaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampY, cpu_r[29], cpu_r[28]);
+}
+
+static void gen_set_zaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]);
+}
+
+static TCGv gen_get_addr(TCGv H, TCGv M, TCGv L)
+{
+    TCGv addr = tcg_temp_new_i32();
+
+    tcg_gen_deposit_tl(addr, M, H, 8, 8);
+    tcg_gen_deposit_tl(addr, L, addr, 8, 16);
+
+    return addr;
+}
+
+static TCGv gen_get_xaddr(void)
+{
+    return gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]);
+}
+
+static TCGv gen_get_yaddr(void)
+{
+    return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
+}
+
+static TCGv gen_get_zaddr(void)
+{
+    return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
+}
+
+/*
+ *  Adds two registers and the contents of the C Flag and places the result in
+ *  the destination register Rd.
+ */
+int avr_translate_ADC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[ADC_Rd(opcode)];
+    TCGv Rr = cpu_r[ADC_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_add_tl(R, Rd, Rr); /* R = Rd + Rr + Cf */
+    tcg_gen_add_tl(R, R, cpu_Cf);
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_add_CHf(R, Rd, Rr);
+    gen_add_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Adds two registers without the C Flag and places the result in the
+ *  destination register Rd.
+ */
+int avr_translate_ADD(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[ADD_Rd(opcode)];
+    TCGv Rr = cpu_r[ADD_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_add_tl(R, Rd, Rr); /* Rd = Rd + Rr */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_add_CHf(R, Rd, Rr);
+    gen_add_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Adds an immediate value (0 - 63) to a register pair and places the result
+ *  in the register pair. This instruction operates on the upper four register
+ *  pairs, and is well suited for operations on the pointer registers.  This
+ *  instruction is not available in all devices. Refer to the device specific
+ *  instruction set summary.
+ */
+int avr_translate_ADIW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_ADIW_SBIW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv RdL = cpu_r[24 + 2 * ADIW_Rd(opcode)];
+    TCGv RdH = cpu_r[25 + 2 * ADIW_Rd(opcode)];
+    int Imm = (ADIW_Imm(opcode));
+    TCGv R = tcg_temp_new_i32();
+    TCGv Rd = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
+    tcg_gen_addi_tl(R, Rd, Imm); /* R = Rd + Imm */
+    tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
+
+    /* Cf */
+    tcg_gen_andc_tl(cpu_Cf, Rd, R); /* Cf = Rd & ~R */
+    tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15);
+
+    /* Vf */
+    tcg_gen_andc_tl(cpu_Vf, R, Rd); /* Vf = R & ~Rd */
+    tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15);
+
+    /* Zf */
+    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+
+    /* Nf */
+    tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
+
+    /* Sf */
+    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);/* Sf = Nf ^ Vf */
+
+    /* R */
+    tcg_gen_andi_tl(RdL, R, 0xff);
+    tcg_gen_shri_tl(RdH, R, 8);
+
+    tcg_temp_free_i32(Rd);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical AND between the contents of register Rd and register
+ *  Rr and places the result in the destination register Rd.
+ */
+int avr_translate_AND(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[AND_Rd(opcode)];
+    TCGv Rr = cpu_r[AND_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_and_tl(R, Rd, Rr); /* Rd = Rd and Rr */
+
+    /* Vf */
+    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+
+    /* Zf */
+    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical AND between the contents of register Rd and a constant
+ *  and places the result in the destination register Rd.
+ */
+int avr_translate_ANDI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + ANDI_Rd(opcode)];
+    int Imm = (ANDI_Imm(opcode));
+
+    /* op */
+    tcg_gen_andi_tl(Rd, Rd, Imm); /* Rd = Rd & Imm */
+
+    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+    gen_ZNSf(Rd);
+
+    return BS_NONE;
+}
+
+/*
+ *  Shifts all bits in Rd one place to the right. Bit 7 is held constant. Bit 0
+ *  is loaded into the C Flag of the SREG. This operation effectively divides a
+ *  signed value by two without changing its sign. The Carry Flag can be used to
+ *  round the result.
+ */
+int avr_translate_ASR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[ASR_Rd(opcode)];
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_andi_tl(t1, Rd, 0x80); /* t1 = (Rd & 0x80) | (Rd >> 1) */
+    tcg_gen_shri_tl(t2, Rd, 1);
+    tcg_gen_or_tl(t1, t1, t2);
+
+    /* Cf */
+    tcg_gen_andi_tl(cpu_Cf, Rd, 1); /* Cf = Rd(0) */
+
+    /* Vf */
+    tcg_gen_and_tl(cpu_Vf, cpu_Nf, cpu_Cf);/* Vf = Nf & Cf */
+
+    gen_ZNSf(t1);
+
+    /* op */
+    tcg_gen_mov_tl(Rd, t1);
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+
+    return BS_NONE;
+}
+
+/*
+ *  Clears a single Flag in SREG.
+ */
+int avr_translate_BCLR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    switch (BCLR_Bit(opcode)) {
+    case 0x00:
+        tcg_gen_movi_tl(cpu_Cf, 0x00);
+        break;
+    case 0x01:
+        tcg_gen_movi_tl(cpu_Zf, 0x01);
+        break;
+    case 0x02:
+        tcg_gen_movi_tl(cpu_Nf, 0x00);
+        break;
+    case 0x03:
+        tcg_gen_movi_tl(cpu_Vf, 0x00);
+        break;
+    case 0x04:
+        tcg_gen_movi_tl(cpu_Sf, 0x00);
+        break;
+    case 0x05:
+        tcg_gen_movi_tl(cpu_Hf, 0x00);
+        break;
+    case 0x06:
+        tcg_gen_movi_tl(cpu_Tf, 0x00);
+        break;
+    case 0x07:
+        tcg_gen_movi_tl(cpu_If, 0x00);
+        break;
+    }
+
+    return BS_NONE;
+}
+
+/*
+ *  Copies the T Flag in the SREG (Status Register) to bit b in register Rd.
+ */
+int avr_translate_BLD(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[BLD_Rd(opcode)];
+    TCGv t1 = tcg_temp_new_i32();
+
+    tcg_gen_andi_tl(Rd, Rd, ~(1u << BLD_Bit(opcode))); /* clear bit */
+    tcg_gen_shli_tl(t1, cpu_Tf, BLD_Bit(opcode)); /* create mask */
+    tcg_gen_or_tl(Rd, Rd, t1);
+
+    tcg_temp_free_i32(t1);
+
+    return BS_NONE;
+}
+
+/*
+ *  Conditional relative branch. Tests a single bit in SREG and branches
+ *  relatively to PC if the bit is cleared. This instruction branches relatively
+ *  to PC in either direction (PC - 63 < = destination <= PC + 64). The
+ *  parameter k is the offset from PC and is represented in two's complement
+ *  form.
+ */
+int avr_translate_BRBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGLabel *taken = gen_new_label();
+    int Imm = sextract32(BRBC_Imm(opcode), 0, 7);
+
+    switch (BRBC_Bit(opcode)) {
+    case 0x00:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Cf, 0, taken);
+        break;
+    case 0x01:
+        tcg_gen_brcondi_i32(TCG_COND_NE, cpu_Zf, 0, taken);
+        break;
+    case 0x02:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Nf, 0, taken);
+        break;
+    case 0x03:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Vf, 0, taken);
+        break;
+    case 0x04:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Sf, 0, taken);
+        break;
+    case 0x05:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Hf, 0, taken);
+        break;
+    case 0x06:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Tf, 0, taken);
+        break;
+    case 0x07:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_If, 0, taken);
+        break;
+    }
+
+    gen_goto_tb(env, ctx, 1, ctx->inst[0].npc);
+    gen_set_label(taken);
+    gen_goto_tb(env, ctx, 0, ctx->inst[0].npc + Imm);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Conditional relative branch. Tests a single bit in SREG and branches
+ *  relatively to PC if the bit is set. This instruction branches relatively to
+ *  PC in either direction (PC - 63 < = destination <= PC + 64). The parameter k
+ *  is the offset from PC and is represented in two's complement form.
+ */
+int avr_translate_BRBS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGLabel *taken = gen_new_label();
+    int Imm = sextract32(BRBS_Imm(opcode), 0, 7);
+
+    switch (BRBS_Bit(opcode)) {
+    case 0x00:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Cf, 1, taken);
+        break;
+    case 0x01:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Zf, 0, taken);
+        break;
+    case 0x02:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Nf, 1, taken);
+        break;
+    case 0x03:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Vf, 1, taken);
+        break;
+    case 0x04:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Sf, 1, taken);
+        break;
+    case 0x05:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Hf, 1, taken);
+        break;
+    case 0x06:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Tf, 1, taken);
+        break;
+    case 0x07:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_If, 1, taken);
+        break;
+    }
+
+    gen_goto_tb(env, ctx, 1, ctx->inst[0].npc);
+    gen_set_label(taken);
+    gen_goto_tb(env, ctx, 0, ctx->inst[0].npc + Imm);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Sets a single Flag or bit in SREG.
+ */
+int avr_translate_BSET(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    switch (BSET_Bit(opcode)) {
+    case 0x00:
+        tcg_gen_movi_tl(cpu_Cf, 0x01);
+        break;
+    case 0x01:
+        tcg_gen_movi_tl(cpu_Zf, 0x00);
+        break;
+    case 0x02:
+        tcg_gen_movi_tl(cpu_Nf, 0x01);
+        break;
+    case 0x03:
+        tcg_gen_movi_tl(cpu_Vf, 0x01);
+        break;
+    case 0x04:
+        tcg_gen_movi_tl(cpu_Sf, 0x01);
+        break;
+    case 0x05:
+        tcg_gen_movi_tl(cpu_Hf, 0x01);
+        break;
+    case 0x06:
+        tcg_gen_movi_tl(cpu_Tf, 0x01);
+        break;
+    case 0x07:
+        tcg_gen_movi_tl(cpu_If, 0x01);
+        break;
+    }
+
+    return BS_NONE;
+}
+
+/*
+ *  The BREAK instruction is used by the On-chip Debug system, and is
+ *  normally not used in the application software. When the BREAK instruction is
+ *  executed, the AVR CPU is set in the Stopped Mode. This gives the On-chip
+ *  Debugger access to internal resources.  If any Lock bits are set, or either
+ *  the JTAGEN or OCDEN Fuses are unprogrammed, the CPU will treat the BREAK
+ *  instruction as a NOP and will not enter the Stopped mode.  This instruction
+ *  is not available in all devices. Refer to the device specific instruction
+ *  set summary.
+ */
+int avr_translate_BREAK(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_BREAK) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    /* TODO:   ??? */
+    return BS_NONE;
+}
+
+/*
+ *  Stores bit b from Rd to the T Flag in SREG (Status Register).
+ */
+int avr_translate_BST(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[BST_Rd(opcode)];
+
+    tcg_gen_andi_tl(cpu_Tf, Rd, 1 << BST_Bit(opcode));
+    tcg_gen_shri_tl(cpu_Tf, cpu_Tf, BST_Bit(opcode));
+
+    return BS_NONE;
+}
+
+/*
+ *  Calls to a subroutine within the entire Program memory. The return
+ *  address (to the instruction after the CALL) will be stored onto the Stack.
+ *  (See also RCALL). The Stack Pointer uses a post-decrement scheme during
+ *  CALL.  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+int avr_translate_CALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_JMP_CALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    int Imm = CALL_Imm(opcode);
+    int ret = ctx->inst[0].npc;
+
+    gen_push_ret(env, ret);
+
+    gen_goto_tb(env, ctx, 0, Imm);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Clears a specified bit in an I/O Register. This instruction operates on
+ *  the lower 32 I/O Registers -- addresses 0-31.
+ */
+int avr_translate_CBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv data = tcg_temp_new_i32();
+    TCGv port = tcg_const_i32(CBI_Imm(opcode));
+
+    gen_helper_inb(data, cpu_env, port);
+    tcg_gen_andi_tl(data, data, ~(1 << CBI_Bit(opcode)));
+    gen_helper_outb(cpu_env, port, data);
+
+    tcg_temp_free_i32(data);
+    tcg_temp_free_i32(port);
+
+    return BS_NONE;
+}
+
+/*
+ *  Clears the specified bits in register Rd. Performs the logical AND
+ *  between the contents of register Rd and the complement of the constant mask
+ *  K. The result will be placed in register Rd.
+ */
+int avr_translate_COM(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[COM_Rd(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    tcg_gen_xori_tl(Rd, Rd, 0xff);
+
+    tcg_gen_movi_tl(cpu_Cf, 1); /* Cf = 1 */
+    tcg_gen_movi_tl(cpu_Vf, 0); /* Vf = 0 */
+    gen_ZNSf(Rd);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a compare between two registers Rd and Rr.
+ *  None of the registers are changed. All conditional branches can be used
+ *  after this instruction.
+ */
+int avr_translate_CP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[CP_Rd(opcode)];
+    TCGv Rr = cpu_r[CP_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a compare between two registers Rd and Rr and
+ *  also takes into account the previous carry. None of the registers are
+ *  changed. All conditional branches can be used after this instruction.
+ */
+int avr_translate_CPC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[CPC_Rd(opcode)];
+    TCGv Rr = cpu_r[CPC_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+    tcg_gen_sub_tl(R, R, cpu_Cf);
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_NSf(R);
+
+    /* Previous value remains unchanged when the result is zero;
+     * cleared otherwise.
+     */
+    tcg_gen_or_tl(cpu_Zf, cpu_Zf, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a compare between register Rd and a constant.
+ *  The register is not changed. All conditional branches can be used after this
+ *  instruction.
+ */
+int avr_translate_CPI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + CPI_Rd(opcode)];
+    int Imm = CPI_Imm(opcode);
+    TCGv Rr = tcg_const_i32(Imm);
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    tcg_temp_free_i32(R);
+    tcg_temp_free_i32(Rr);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a compare between two registers Rd and Rr, and
+ *  skips the next instruction if Rd = Rr.
+ */
+int avr_translate_CPSE(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[CPSE_Rd(opcode)];
+    TCGv Rr = cpu_r[CPSE_Rr(opcode)];
+    TCGLabel *skip = gen_new_label();
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_brcond_i32(TCG_COND_EQ, Rd, Rr, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Subtracts one -1- from the contents of register Rd and places the result
+ *  in the destination register Rd.  The C Flag in SREG is not affected by the
+ *  operation, thus allowing the DEC instruction to be used on a loop counter in
+ *  multiple-precision computations.  When operating on unsigned values, only
+ *  BREQ and BRNE branches can be expected to perform consistently.  When
+ *  operating on two's complement values, all signed branches are available.
+ */
+int avr_translate_DEC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[DEC_Rd(opcode)];
+
+    tcg_gen_subi_tl(Rd, Rd, 1); /* Rd = Rd - 1 */
+    tcg_gen_andi_tl(Rd, Rd, 0xff); /* make it 8 bits */
+
+        /* cpu_Vf = Rd == 0x7f */
+    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x7f);
+    gen_ZNSf(Rd);
+
+    return BS_NONE;
+}
+
+/*
+ *  The module is an instruction set extension to the AVR CPU, performing
+ *  DES iterations. The 64-bit data block (plaintext or ciphertext) is placed in
+ *  the CPU register file, registers R0-R7, where LSB of data is placed in LSB
+ *  of R0 and MSB of data is placed in MSB of R7. The full 64-bit key (including
+ *  parity bits) is placed in registers R8- R15, organized in the register file
+ *  with LSB of key in LSB of R8 and MSB of key in MSB of R15. Executing one DES
+ *  instruction performs one round in the DES algorithm. Sixteen rounds must be
+ *  executed in increasing order to form the correct DES ciphertext or
+ *  plaintext. Intermediate results are stored in the register file (R0-R15)
+ *  after each DES instruction. The instruction's operand (K) determines which
+ *  round is executed, and the half carry flag (H) determines whether encryption
+ *  or decryption is performed.  The DES algorithm is described in
+ *  "Specifications for the Data Encryption Standard" (Federal Information
+ *  Processing Standards Publication 46). Intermediate results in this
+ *  implementation differ from the standard because the initial permutation and
+ *  the inverse initial permutation are performed each iteration. This does not
+ *  affect the result in the final ciphertext or plaintext, but reduces
+ *  execution time.
+ */
+int avr_translate_DES(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    /* TODO: */
+    if (avr_feature(env, AVR_FEATURE_DES) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    return BS_NONE;
+}
+
+/*
+ *  Indirect call of a subroutine pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File and the EIND Register in the I/O space. This
+ *  instruction allows for indirect calls to the entire 4M (words) Program
+ *  memory space. See also ICALL. The Stack Pointer uses a post-decrement scheme
+ *  during EICALL.  This instruction is not available in all devices. Refer to
+ *  the device specific instruction set summary.
+ */
+int avr_translate_EICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_EIJMP_EICALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    int ret = ctx->inst[0].npc;
+
+    gen_push_ret(env, ret);
+
+    gen_jmp_ez();
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Indirect jump to the address pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File and the EIND Register in the I/O space. This
+ *  instruction allows for indirect jumps to the entire 4M (words) Program
+ *  memory space. See also IJMP.  This instruction is not available in all
+ *  devices. Refer to the device specific instruction set summary.
+ */
+int avr_translate_EIJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_EIJMP_EICALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    gen_jmp_ez();
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Loads one byte pointed to by the Z-register and the RAMPZ Register in
+ *  the I/O space, and places this byte in the destination register Rd. This
+ *  instruction features a 100% space effective constant initialization or
+ *  constant data fetch. The Program memory is organized in 16-bit words while
+ *  the Z-pointer is a byte address. Thus, the least significant bit of the
+ *  Z-pointer selects either low byte (ZLSB = 0) or high byte (ZLSB = 1). This
+ *  instruction can address the entire Program memory space. The Z-pointer
+ *  Register can either be left unchanged by the operation, or it can be
+ *  incremented. The incrementation applies to the entire 24-bit concatenation
+ *  of the RAMPZ and Z-pointer Registers.  Devices with Self-Programming
+ *  capability can use the ELPM instruction to read the Fuse and Lock bit value.
+ *  Refer to the device documentation for a detailed description.  This
+ *  instruction is not available in all devices. Refer to the device specific
+ *  instruction set summary.
+ */
+int avr_translate_ELPM1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_ELPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[0];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_ELPM2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_ELPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[ELPM2_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_ELPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_ELPMX) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[ELPMX_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical EOR between the contents of register Rd and
+ *  register Rr and places the result in the destination register Rd.
+ */
+int avr_translate_EOR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[EOR_Rd(opcode)];
+    TCGv Rr = cpu_r[EOR_Rr(opcode)];
+
+    tcg_gen_xor_tl(Rd, Rd, Rr);
+
+    tcg_gen_movi_tl(cpu_Vf, 0);
+    gen_ZNSf(Rd);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned
+ *  multiplication and shifts the result one bit left.
+ */
+int avr_translate_FMUL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + FMUL_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + FMUL_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
+    tcg_gen_shli_tl(R, R, 1);
+
+    tcg_gen_andi_tl(R0, R, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_andi_tl(R1, R, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
+ *  and shifts the result one bit left.
+ */
+int avr_translate_FMULS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + FMULS_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + FMULS_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+    tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
+    tcg_gen_mul_tl(R, t0, t1); /* R = Rd *Rr */
+    tcg_gen_shli_tl(R, R, 1);
+
+    tcg_gen_andi_tl(R0, R, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_andi_tl(R1, R, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
+ *  and shifts the result one bit left.
+ */
+int avr_translate_FMULSU(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + FMULSU_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + FMULSU_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+    tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
+    tcg_gen_shli_tl(R, R, 1);
+
+    tcg_gen_andi_tl(R0, R, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_andi_tl(R1, R, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Calls to a subroutine within the entire 4M (words) Program memory. The
+ *  return address (to the instruction after the CALL) will be stored onto the
+ *  Stack. See also RCALL. The Stack Pointer uses a post-decrement scheme during
+ *  CALL.  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+int avr_translate_ICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_IJMP_ICALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    int ret = ctx->inst[0].npc;
+
+    gen_push_ret(env, ret);
+    gen_jmp_z();
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Indirect jump to the address pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File. The Z-pointer Register is 16 bits wide and
+ *  allows jump within the lowest 64K words (128KB) section of Program memory.
+ *  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+int avr_translate_IJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_IJMP_ICALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    gen_jmp_z();
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Loads data from the I/O Space (Ports, Timers, Configuration Registers,
+ *  etc.) into register Rd in the Register File.
+ */
+int avr_translate_IN(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[IN_Rd(opcode)];
+    int Imm = IN_Imm(opcode);
+    TCGv port = tcg_const_i32(Imm);
+
+    gen_helper_inb(Rd, cpu_env, port);
+
+    tcg_temp_free_i32(port);
+
+    return BS_NONE;
+}
+
+/*
+ *  Adds one -1- to the contents of register Rd and places the result in the
+ *  destination register Rd.  The C Flag in SREG is not affected by the
+ *  operation, thus allowing the INC instruction to be used on a loop counter in
+ *  multiple-precision computations.  When operating on unsigned numbers, only
+ *  BREQ and BRNE branches can be expected to perform consistently. When
+ *  operating on two's complement values, all signed branches are available.
+ */
+int avr_translate_INC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[INC_Rd(opcode)];
+
+    tcg_gen_addi_tl(Rd, Rd, 1);
+    tcg_gen_andi_tl(Rd, Rd, 0xff);
+
+        /* cpu_Vf = Rd == 0x80 */
+    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x80);
+    gen_ZNSf(Rd);
+    return BS_NONE;
+}
+
+/*
+ *  Jump to an address within the entire 4M (words) Program memory. See also
+ *  RJMP.  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.0
+ */
+int avr_translate_JMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_JMP_CALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    gen_goto_tb(env, ctx, 0, JMP_Imm(opcode));
+    return BS_BRANCH;
+}
+
+/*
+ *  Load one byte indirect from data space to register and stores an clear
+ *  the bits in data space specified by the register. The instruction can only
+ *  be used towards internal SRAM.  The data location is pointed to by the Z (16
+ *  bits) Pointer Register in the Register File. Memory access is limited to the
+ *  current data segment of 64KB. To access another data segment in devices with
+ *  more than 64KB data space, the RAMPZ in register in the I/O area has to be
+ *  changed.  The Z-pointer Register is left unchanged by the operation. This
+ *  instruction is especially suited for clearing status bits stored in SRAM.
+ */
+static void gen_data_store(DisasContext *ctx, TCGv data, TCGv addr)
+{
+    if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) {
+        gen_helper_fullwr(cpu_env, data, addr);
+    } else {
+        tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX); /* mem[addr] = data */
+    }
+}
+
+static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr)
+{
+    if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) {
+        gen_helper_fullrd(data, cpu_env, addr);
+    } else {
+        tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX); /* data = mem[addr] */
+    }
+}
+
+int avr_translate_LAC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rr = cpu_r[LAC_Rr(opcode)];
+    TCGv addr = gen_get_zaddr();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+        /* t1 = t0 & (0xff - Rr) = t0 and ~Rr */
+    tcg_gen_andc_tl(t1, t0, Rr);
+
+    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Load one byte indirect from data space to register and set bits in data
+ *  space specified by the register. The instruction can only be used towards
+ *  internal SRAM.  The data location is pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File. Memory access is limited to the current data
+ *  segment of 64KB. To access another data segment in devices with more than
+ *  64KB data space, the RAMPZ in register in the I/O area has to be changed.
+ *  The Z-pointer Register is left unchanged by the operation. This instruction
+ *  is especially suited for setting status bits stored in SRAM.
+ */
+int avr_translate_LAS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rr = cpu_r[LAS_Rr(opcode)];
+    TCGv addr = gen_get_zaddr();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+    tcg_gen_or_tl(t1, t0, Rr);
+
+    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Load one byte indirect from data space to register and toggles bits in
+ *  the data space specified by the register.  The instruction can only be used
+ *  towards SRAM.  The data location is pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File. Memory access is limited to the current data
+ *  segment of 64KB. To access another data segment in devices with more than
+ *  64KB data space, the RAMPZ in register in the I/O area has to be changed.
+ *  The Z-pointer Register is left unchanged by the operation. This instruction
+ *  is especially suited for changing status bits stored in SRAM.
+ */
+int avr_translate_LAT(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rr = cpu_r[LAT_Rr(opcode)];
+    TCGv addr = gen_get_zaddr();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+    tcg_gen_xor_tl(t1, t0, Rr);
+
+    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte indirect from the data space to a register. For parts
+ *  with SRAM, the data space consists of the Register File, I/O memory and
+ *  internal SRAM (and external SRAM if applicable). For parts without SRAM, the
+ *  data space consists of the Register File only. In some parts the Flash
+ *  Memory has been mapped to the data space and can be read using this command.
+ *  The EEPROM has a separate address space.  The data location is pointed to by
+ *  the X (16 bits) Pointer Register in the Register File. Memory access is
+ *  limited to the current data segment of 64KB. To access another data segment
+ *  in devices with more than 64KB data space, the RAMPX in register in the I/O
+ *  area has to be changed.  The X-pointer Register can either be left unchanged
+ *  by the operation, or it can be post-incremented or predecremented.  These
+ *  features are especially suited for accessing arrays, tables, and Stack
+ *  Pointer usage of the X-pointer Register. Note that only the low byte of the
+ *  X-pointer is updated in devices with no more than 256 bytes data space. For
+ *  such devices, the high byte of the pointer is not used by this instruction
+ *  and can be used for other purposes. The RAMPX Register in the I/O area is
+ *  updated in parts with more than 64KB data space or more than 64KB Program
+ *  memory, and the increment/decrement is added to the entire 24-bit address on
+ *  such devices.  Not all variants of this instruction is available in all
+ *  devices. Refer to the device specific instruction set summary.  In the
+ *  Reduced Core tinyAVR the LD instruction can be used to achieve the same
+ *  operation as LPM since the program memory is mapped to the data memory
+ *  space.
+ */
+int avr_translate_LDX1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDX1_Rd(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    gen_data_load(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_LDX2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDX2_Rd(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    gen_data_load(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_LDX3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDX3_Rd(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_load(ctx, Rd, addr);
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte indirect with or without displacement from the data space
+ *  to a register. For parts with SRAM, the data space consists of the Register
+ *  File, I/O memory and internal SRAM (and external SRAM if applicable). For
+ *  parts without SRAM, the data space consists of the Register File only. In
+ *  some parts the Flash Memory has been mapped to the data space and can be
+ *  read using this command. The EEPROM has a separate address space.  The data
+ *  location is pointed to by the Y (16 bits) Pointer Register in the Register
+ *  File. Memory access is limited to the current data segment of 64KB. To
+ *  access another data segment in devices with more than 64KB data space, the
+ *  RAMPY in register in the I/O area has to be changed.  The Y-pointer Register
+ *  can either be left unchanged by the operation, or it can be post-incremented
+ *  or predecremented.  These features are especially suited for accessing
+ *  arrays, tables, and Stack Pointer usage of the Y-pointer Register. Note that
+ *  only the low byte of the Y-pointer is updated in devices with no more than
+ *  256 bytes data space. For such devices, the high byte of the pointer is not
+ *  used by this instruction and can be used for other purposes. The RAMPY
+ *  Register in the I/O area is updated in parts with more than 64KB data space
+ *  or more than 64KB Program memory, and the increment/decrement/displacement
+ *  is added to the entire 24-bit address on such devices.  Not all variants of
+ *  this instruction is available in all devices. Refer to the device specific
+ *  instruction set summary.  In the Reduced Core tinyAVR the LD instruction can
+ *  be used to achieve the same operation as LPM since the program memory is
+ *  mapped to the data memory space.
+ */
+int avr_translate_LDY2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDY2_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    gen_data_load(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_LDY3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDY3_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_load(ctx, Rd, addr);
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_LDDY(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDDY_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    tcg_gen_addi_tl(addr, addr, LDDY_Imm(opcode)); /* addr = addr + q */
+    gen_data_load(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte indirect with or without displacement from the data space
+ *  to a register. For parts with SRAM, the data space consists of the Register
+ *  File, I/O memory and internal SRAM (and external SRAM if applicable). For
+ *  parts without SRAM, the data space consists of the Register File only. In
+ *  some parts the Flash Memory has been mapped to the data space and can be
+ *  read using this command. The EEPROM has a separate address space.  The data
+ *  location is pointed to by the Z (16 bits) Pointer Register in the Register
+ *  File. Memory access is limited to the current data segment of 64KB. To
+ *  access another data segment in devices with more than 64KB data space, the
+ *  RAMPZ in register in the I/O area has to be changed.  The Z-pointer Register
+ *  can either be left unchanged by the operation, or it can be post-incremented
+ *  or predecremented.  These features are especially suited for Stack Pointer
+ *  usage of the Z-pointer Register, however because the Z-pointer Register can
+ *  be used for indirect subroutine calls, indirect jumps and table lookup, it
+ *  is often more convenient to use the X or Y-pointer as a dedicated Stack
+ *  Pointer. Note that only the low byte of the Z-pointer is updated in devices
+ *  with no more than 256 bytes data space. For such devices, the high byte of
+ *  the pointer is not used by this instruction and can be used for other
+ *  purposes. The RAMPZ Register in the I/O area is updated in parts with more
+ *  than 64KB data space or more than 64KB Program memory, and the
+ *  increment/decrement/displacement is added to the entire 24-bit address on
+ *  such devices.  Not all variants of this instruction is available in all
+ *  devices. Refer to the device specific instruction set summary.  In the
+ *  Reduced Core tinyAVR the LD instruction can be used to achieve the same
+ *  operation as LPM since the program memory is mapped to the data memory
+ *  space.  For using the Z-pointer for table lookup in Program memory see the
+ *  LPM and ELPM instructions.
+ */
+int avr_translate_LDZ2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDZ2_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    gen_data_load(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_LDZ3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDZ3_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_load(ctx, Rd, addr);
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_LDDZ(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDDZ_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_addi_tl(addr, addr, LDDZ_Imm(opcode));
+                                                    /* addr = addr + q */
+    gen_data_load(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+    Loads an 8 bit constant directly to register 16 to 31.
+ */
+int avr_translate_LDI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + LDI_Rd(opcode)];
+    int imm = LDI_Imm(opcode);
+
+    tcg_gen_movi_tl(Rd, imm);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte from the data space to a register. For parts with SRAM,
+ *  the data space consists of the Register File, I/O memory and internal SRAM
+ *  (and external SRAM if applicable). For parts without SRAM, the data space
+ *  consists of the register file only. The EEPROM has a separate address space.
+ *  A 16-bit address must be supplied. Memory access is limited to the current
+ *  data segment of 64KB. The LDS instruction uses the RAMPD Register to access
+ *  memory above 64KB. To access another data segment in devices with more than
+ *  64KB data space, the RAMPD in register in the I/O area has to be changed.
+ *  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+int avr_translate_LDS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDS_Rd(opcode)];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_rampD;
+
+    tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
+    tcg_gen_shli_tl(addr, addr, 16);
+    tcg_gen_ori_tl(addr, addr, LDS_Imm(opcode));
+
+    gen_data_load(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte pointed to by the Z-register into the destination
+ *  register Rd. This instruction features a 100% space effective constant
+ *  initialization or constant data fetch. The Program memory is organized in
+ *  16-bit words while the Z-pointer is a byte address. Thus, the least
+ *  significant bit of the Z-pointer selects either low byte (ZLSB = 0) or high
+ *  byte (ZLSB = 1). This instruction can address the first 64KB (32K words) of
+ *  Program memory. The Zpointer Register can either be left unchanged by the
+ *  operation, or it can be incremented. The incrementation does not apply to
+ *  the RAMPZ Register.  Devices with Self-Programming capability can use the
+ *  LPM instruction to read the Fuse and Lock bit values.  Refer to the device
+ *  documentation for a detailed description.  The LPM instruction is not
+ *  available in all devices. Refer to the device specific instruction set
+ *  summary
+ */
+int avr_translate_LPM1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_LPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[0];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_r[31];
+    TCGv L = cpu_r[30];
+
+    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+    tcg_gen_or_tl(addr, addr, L);
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_LPM2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_LPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[LPM2_Rd(opcode)];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_r[31];
+    TCGv L = cpu_r[30];
+
+    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+    tcg_gen_or_tl(addr, addr, L);
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_LPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_LPMX) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[LPMX_Rd(opcode)];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_r[31];
+    TCGv L = cpu_r[30];
+
+    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+    tcg_gen_or_tl(addr, addr, L);
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    tcg_gen_andi_tl(L, addr, 0xff);
+
+    tcg_gen_shri_tl(addr, addr, 8);
+    tcg_gen_andi_tl(H, addr, 0xff);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Shifts all bits in Rd one place to the right. Bit 7 is cleared. Bit 0 is
+ *  loaded into the C Flag of the SREG. This operation effectively divides an
+ *  unsigned value by two. The C Flag can be used to round the result.
+ */
+int avr_translate_LSR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LSR_Rd(opcode)];
+
+    tcg_gen_andi_tl(cpu_Cf, Rd, 1);
+
+    tcg_gen_shri_tl(Rd, Rd, 1);
+
+    gen_ZNSf(Rd);
+    tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
+    return BS_NONE;
+}
+
+/*
+ *  This instruction makes a copy of one register into another. The source
+ *  register Rr is left unchanged, while the destination register Rd is loaded
+ *  with a copy of Rr.
+ */
+int avr_translate_MOV(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[MOV_Rd(opcode)];
+    TCGv Rr = cpu_r[MOV_Rr(opcode)];
+
+    tcg_gen_mov_tl(Rd, Rr);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction makes a copy of one register pair into another register
+ *  pair. The source register pair Rr+1:Rr is left unchanged, while the
+ *  destination register pair Rd+1:Rd is loaded with a copy of Rr + 1:Rr.  This
+ *  instruction is not available in all devices. Refer to the device specific
+ *  instruction set summary.
+ */
+int avr_translate_MOVW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_MOVW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv RdL = cpu_r[MOVW_Rd(opcode) * 2 + 0];
+    TCGv RdH = cpu_r[MOVW_Rd(opcode) * 2 + 1];
+    TCGv RrL = cpu_r[MOVW_Rr(opcode) * 2 + 0];
+    TCGv RrH = cpu_r[MOVW_Rr(opcode) * 2 + 1];
+
+    tcg_gen_mov_tl(RdH, RrH);
+    tcg_gen_mov_tl(RdL, RrL);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication.
+ */
+int avr_translate_MUL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[MUL_Rd(opcode)];
+    TCGv Rr = cpu_r[MUL_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
+
+    tcg_gen_mov_tl(R0, R);
+    tcg_gen_andi_tl(R0, R0, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_mov_tl(R1, R);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
+    tcg_gen_mov_tl(cpu_Zf, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication.
+ */
+int avr_translate_MULS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + MULS_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + MULS_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+    tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
+    tcg_gen_mul_tl(R, t0, t1); /* R = Rd * Rr */
+
+    tcg_gen_mov_tl(R0, R);
+    tcg_gen_andi_tl(R0, R0, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_mov_tl(R1, R);
+    tcg_gen_andi_tl(R1, R0, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
+    tcg_gen_mov_tl(cpu_Zf, R);
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a
+ *  signed and an unsigned number.
+ */
+int avr_translate_MULSU(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + MULSU_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + MULSU_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+    tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
+
+    tcg_gen_mov_tl(R0, R);
+    tcg_gen_andi_tl(R0, R0, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_mov_tl(R1, R);
+    tcg_gen_andi_tl(R1, R0, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+    tcg_gen_mov_tl(cpu_Zf, R);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Replaces the contents of register Rd with its two's complement; the
+ *  value $80 is left unchanged.
+ */
+int avr_translate_NEG(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[SUB_Rd(opcode)];
+    TCGv t0 = tcg_const_i32(0);
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, t0, Rd); /* R = 0 - Rd */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, t0, Rd);
+    gen_sub_Vf(R, t0, Rd);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a single cycle No Operation.
+ */
+int avr_translate_NOP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+
+    /* NOP */
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical OR between the contents of register Rd and register
+ *  Rr and places the result in the destination register Rd.
+ */
+int avr_translate_OR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[OR_Rd(opcode)];
+    TCGv Rr = cpu_r[OR_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    tcg_gen_or_tl(R, Rd, Rr);
+
+    tcg_gen_movi_tl(cpu_Vf, 0);
+    gen_ZNSf(R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical OR between the contents of register Rd and a
+ *  constant and places the result in the destination register Rd.
+ */
+int avr_translate_ORI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + ORI_Rd(opcode)];
+    int Imm = (ORI_Imm(opcode));
+
+    tcg_gen_ori_tl(Rd, Rd, Imm); /* Rd = Rd | Imm */
+
+    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+    gen_ZNSf(Rd);
+
+    return BS_NONE;
+}
+
+/*
+ *  Stores data from register Rr in the Register File to I/O Space (Ports,
+ *  Timers, Configuration Registers, etc.).
+ */
+int avr_translate_OUT(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[OUT_Rd(opcode)];
+    int Imm = OUT_Imm(opcode);
+    TCGv port = tcg_const_i32(Imm);
+
+    gen_helper_outb(cpu_env, port, Rd);
+
+    tcg_temp_free_i32(port);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction loads register Rd with a byte from the STACK. The Stack
+ *  Pointer is pre-incremented by 1 before the POP.  This instruction is not
+ *  available in all devices. Refer to the device specific instruction set
+ *  summary.
+ */
+int avr_translate_POP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[POP_Rd(opcode)];
+
+    tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+    gen_data_load(ctx, Rd, cpu_sp);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction stores the contents of register Rr on the STACK. The
+ *  Stack Pointer is post-decremented by 1 after the PUSH.  This instruction is
+ *  not available in all devices. Refer to the device specific instruction set
+ *  summary.
+ */
+int avr_translate_PUSH(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[PUSH_Rd(opcode)];
+
+    gen_data_store(ctx, Rd, cpu_sp);
+    tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+    return BS_NONE;
+}
+
+/*
+ *  Relative call to an address within PC - 2K + 1 and PC + 2K (words). The
+ *  return address (the instruction after the RCALL) is stored onto the Stack.
+ *  See also CALL. For AVR microcontrollers with Program memory not exceeding 4K
+ *  words (8KB) this instruction can address the entire memory from every
+ *  address location. The Stack Pointer uses a post-decrement scheme during
+ *  RCALL.
+ */
+int avr_translate_RCALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    int ret = ctx->inst[0].npc;
+    int dst = ctx->inst[0].npc + sextract32(RCALL_Imm(opcode), 0, 12);
+
+    gen_push_ret(env, ret);
+
+    gen_goto_tb(env, ctx, 0, dst);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Returns from subroutine. The return address is loaded from the STACK.
+ *  The Stack Pointer uses a preincrement scheme during RET.
+ */
+int avr_translate_RET(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    gen_pop_ret(env, cpu_pc);
+
+    tcg_gen_exit_tb(0);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Returns from interrupt. The return address is loaded from the STACK and
+ *  the Global Interrupt Flag is set.  Note that the Status Register is not
+ *  automatically stored when entering an interrupt routine, and it is not
+ *  restored when returning from an interrupt routine. This must be handled by
+ *  the application program. The Stack Pointer uses a pre-increment scheme
+ *  during RETI.
+ */
+int avr_translate_RETI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    gen_pop_ret(env, cpu_pc);
+
+    tcg_gen_movi_tl(cpu_If, 1);
+
+    tcg_gen_exit_tb(0);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Relative jump to an address within PC - 2K +1 and PC + 2K (words). For
+ *  AVR microcontrollers with Program memory not exceeding 4K words (8KB) this
+ *  instruction can address the entire memory from every address location. See
+ *  also JMP.
+ */
+int avr_translate_RJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    int dst = ctx->inst[0].npc + sextract32(RJMP_Imm(opcode), 0, 12);
+
+    gen_goto_tb(env, ctx, 0, dst);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Shifts all bits in Rd one place to the right. The C Flag is shifted into
+ *  bit 7 of Rd. Bit 0 is shifted into the C Flag.  This operation, combined
+ *  with ASR, effectively divides multi-byte signed values by two. Combined with
+ *  LSR it effectively divides multi-byte unsigned values by two. The Carry Flag
+ *  can be used to round the result.
+ */
+int avr_translate_ROR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[ROR_Rd(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, cpu_Cf, 7);
+    tcg_gen_andi_tl(cpu_Cf, Rd, 0);
+    tcg_gen_shri_tl(Rd, Rd, 1);
+    tcg_gen_or_tl(Rd, Rd, t0);
+
+    gen_ZNSf(Rd);
+    tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
+
+    tcg_temp_free_i32(t0);
+
+    return BS_NONE;
+}
+
+/*
+ *  Subtracts two registers and subtracts with the C Flag and places the
+ *  result in the destination register Rd.
+ */
+int avr_translate_SBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[SBC_Rd(opcode)];
+    TCGv Rr = cpu_r[SBC_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+    tcg_gen_sub_tl(R, R, cpu_Cf);
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  SBCI -- Subtract Immediate with Carry
+ */
+int avr_translate_SBCI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + SBCI_Rd(opcode)];
+    TCGv Rr = tcg_const_i32(SBCI_Imm(opcode));
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+    tcg_gen_sub_tl(R, R, cpu_Cf);
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+    tcg_temp_free_i32(Rr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Sets a specified bit in an I/O Register. This instruction operates on
+ *  the lower 32 I/O Registers -- addresses 0-31.
+ */
+int avr_translate_SBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv data = tcg_temp_new_i32();
+    TCGv port = tcg_const_i32(SBI_Imm(opcode));
+
+    gen_helper_inb(data, cpu_env, port);
+    tcg_gen_ori_tl(data, data, 1 << SBI_Bit(opcode));
+    gen_helper_outb(cpu_env, port, data);
+
+    tcg_temp_free_i32(port);
+    tcg_temp_free_i32(data);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction tests a single bit in an I/O Register and skips the
+ *  next instruction if the bit is cleared. This instruction operates on the
+ *  lower 32 I/O Registers -- addresses 0-31.
+ */
+int avr_translate_SBIC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv data = tcg_temp_new_i32();
+    TCGv port = tcg_const_i32(SBIC_Imm(opcode));
+    TCGLabel *skip = gen_new_label();
+
+    gen_helper_inb(data, cpu_env, port);
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_andi_tl(data, data, 1 << SBIC_Bit(opcode));
+    tcg_gen_brcondi_i32(TCG_COND_EQ, data, 0, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(port);
+    tcg_temp_free_i32(data);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  This instruction tests a single bit in an I/O Register and skips the
+ *  next instruction if the bit is set. This instruction operates on the lower
+ *  32 I/O Registers -- addresses 0-31.
+ */
+int avr_translate_SBIS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv data = tcg_temp_new_i32();
+    TCGv port = tcg_const_i32(SBIS_Imm(opcode));
+    TCGLabel *skip = gen_new_label();
+
+    gen_helper_inb(data, cpu_env, port);
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_andi_tl(data, data, 1 << SBIS_Bit(opcode));
+    tcg_gen_brcondi_i32(TCG_COND_NE, data, 0, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(port);
+    tcg_temp_free_i32(data);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Subtracts an immediate value (0-63) from a register pair and places the
+ *  result in the register pair. This instruction operates on the upper four
+ *  register pairs, and is well suited for operations on the Pointer Registers.
+ *  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+int avr_translate_SBIW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_ADIW_SBIW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv RdL = cpu_r[24 + 2 * SBIW_Rd(opcode)];
+    TCGv RdH = cpu_r[25 + 2 * SBIW_Rd(opcode)];
+    int Imm = (SBIW_Imm(opcode));
+    TCGv R = tcg_temp_new_i32();
+    TCGv Rd = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
+    tcg_gen_subi_tl(R, Rd, Imm); /* R = Rd - Imm */
+    tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
+
+    /* Cf */
+    tcg_gen_andc_tl(cpu_Cf, R, Rd);
+    tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15); /* Cf = R & ~Rd */
+
+    /* Vf */
+    tcg_gen_andc_tl(cpu_Vf, Rd, R);
+    tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15); /* Vf = Rd & ~R */
+
+    /* Zf */
+    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+
+    /* Nf */
+    tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
+
+    /* Sf */
+    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+
+    /* R */
+    tcg_gen_andi_tl(RdL, R, 0xff);
+    tcg_gen_shri_tl(RdH, R, 8);
+
+    tcg_temp_free_i32(Rd);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction tests a single bit in a register and skips the next
+ *  instruction if the bit is cleared.
+ */
+int avr_translate_SBRC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rr = cpu_r[SBRC_Rr(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+    TCGLabel *skip = gen_new_label();
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_andi_tl(t0, Rr, 1 << SBRC_Bit(opcode));
+    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(t0);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  This instruction tests a single bit in a register and skips the next
+ *  instruction if the bit is set.
+ */
+int avr_translate_SBRS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rr = cpu_r[SBRS_Rr(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+    TCGLabel *skip = gen_new_label();
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_andi_tl(t0, Rr, 1 << SBRS_Bit(opcode));
+    tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(t0);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  This instruction sets the circuit in sleep mode defined by the MCU
+ *  Control Register.
+ */
+int avr_translate_SLEEP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    gen_helper_sleep(cpu_env);
+
+    return BS_EXCP;
+}
+
+/*
+ *  SPM can be used to erase a page in the Program memory, to write a page
+ *  in the Program memory (that is already erased), and to set Boot Loader Lock
+ *  bits. In some devices, the Program memory can be written one word at a time,
+ *  in other devices an entire page can be programmed simultaneously after first
+ *  filling a temporary page buffer. In all cases, the Program memory must be
+ *  erased one page at a time. When erasing the Program memory, the RAMPZ and
+ *  Z-register are used as page address. When writing the Program memory, the
+ *  RAMPZ and Z-register are used as page or word address, and the R1:R0
+ *  register pair is used as data(1). When setting the Boot Loader Lock bits,
+ *  the R1:R0 register pair is used as data. Refer to the device documentation
+ *  for detailed description of SPM usage. This instruction can address the
+ *  entire Program memory.  The SPM instruction is not available in all devices.
+ *  Refer to the device specific instruction set summary.  Note: 1. R1
+ *  determines the instruction high byte, and R0 determines the instruction low
+ *  byte.
+ */
+int avr_translate_SPM(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_SPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    /* TODO:   ??? */
+    return BS_NONE;
+}
+
+int avr_translate_SPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_SPMX) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    /* TODO:   ??? */
+    return BS_NONE;
+}
+
+int avr_translate_STX1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STX1_Rr(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    gen_data_store(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_STX2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STX2_Rr(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    gen_data_store(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_STX3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STX3_Rr(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_store(ctx, Rd, addr);
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_STY2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STY2_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    gen_data_store(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_STY3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STY3_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_store(ctx, Rd, addr);
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_STDY(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STDY_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    tcg_gen_addi_tl(addr, addr, STDY_Imm(opcode));
+                                                /* addr = addr + q */
+    gen_data_store(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_STZ2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STZ2_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    gen_data_store(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_STZ3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STZ3_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_store(ctx, Rd, addr);
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+int avr_translate_STDZ(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STDZ_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_addi_tl(addr, addr, STDZ_Imm(opcode));
+                                                    /* addr = addr + q */
+    gen_data_store(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Stores one byte from a Register to the data space. For parts with SRAM,
+ *  the data space consists of the Register File, I/O memory and internal SRAM
+ *  (and external SRAM if applicable). For parts without SRAM, the data space
+ *  consists of the Register File only. The EEPROM has a separate address space.
+ *  A 16-bit address must be supplied. Memory access is limited to the current
+ *  data segment of 64KB. The STS instruction uses the RAMPD Register to access
+ *  memory above 64KB. To access another data segment in devices with more than
+ *  64KB data space, the RAMPD in register in the I/O area has to be changed.
+ *  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+int avr_translate_STS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STS_Rd(opcode)];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_rampD;
+
+    tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
+    tcg_gen_shli_tl(addr, addr, 16);
+    tcg_gen_ori_tl(addr, addr, STS_Imm(opcode));
+
+    gen_data_store(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Subtracts two registers and places the result in the destination
+ *  register Rd.
+ */
+int avr_translate_SUB(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[SUB_Rd(opcode)];
+    TCGv Rr = cpu_r[SUB_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Subtracts a register and a constant and places the result in the
+ *  destination register Rd. This instruction is working on Register R16 to R31
+ *  and is very well suited for operations on the X, Y, and Z-pointers.
+ */
+int avr_translate_SUBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + SUBI_Rd(opcode)];
+    TCGv Rr = tcg_const_i32(SUBI_Imm(opcode));
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr);
+                                                    /* R = Rd - Imm */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+    tcg_temp_free_i32(Rr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Swaps high and low nibbles in a register.
+ */
+int avr_translate_SWAP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[SWAP_Rd(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    tcg_gen_andi_tl(t0, Rd, 0x0f);
+    tcg_gen_shli_tl(t0, t0, 4);
+    tcg_gen_andi_tl(t1, Rd, 0xf0);
+    tcg_gen_shri_tl(t1, t1, 4);
+    tcg_gen_or_tl(Rd, t0, t1);
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction resets the Watchdog Timer. This instruction must be
+ *  executed within a limited time given by the WD prescaler. See the Watchdog
+ *  Timer hardware specification.
+ */
+int avr_translate_WDR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    gen_helper_wdr(cpu_env);
+
+    return BS_NONE;
+}
+
+/*
+ *  Exchanges one byte indirect between register and data space.  The data
+ *  location is pointed to by the Z (16 bits) Pointer Register in the Register
+ *  File. Memory access is limited to the current data segment of 64KB. To
+ *  access another data segment in devices with more than 64KB data space, the
+ *  RAMPZ in register in the I/O area has to be changed.  The Z-pointer Register
+ *  is left unchanged by the operation. This instruction is especially suited
+ *  for writing/reading status bits stored in SRAM.
+ */
+int avr_translate_XCH(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[XCH_Rd(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv addr = gen_get_zaddr();
+
+    gen_data_load(ctx, t0, addr);
+    gen_data_store(ctx, Rd, addr);
+    tcg_gen_mov_tl(Rd, t0);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
diff --git a/target-avr/translate.h b/target-avr/translate.h
index 99045a3..711886e 100644
--- a/target-avr/translate.h
+++ b/target-avr/translate.h
@@ -33,6 +33,7 @@
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
 #include "exec/log.h"
+#include "translate-inst.h"
 
 extern TCGv_env cpu_env;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 08/13] target-avr: instruction decoder generator
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (6 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 07/13] target-avr: adding instruction translation Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 09/13] target-avr: adding instruction decoder Richard Henderson
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-9-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/cpugen/CMakeLists.txt           |  38 +++
 target-avr/cpugen/README.md                |  17 ++
 target-avr/cpugen/cpu/avr.yaml             | 213 ++++++++++++++
 target-avr/cpugen/src/CMakeLists.txt       |  62 ++++
 target-avr/cpugen/src/cpugen.cpp           | 457 +++++++++++++++++++++++++++++
 target-avr/cpugen/src/utils.cpp            |  26 ++
 target-avr/cpugen/src/utils.h              |  78 +++++
 target-avr/cpugen/xsl/decode.c.xsl         | 103 +++++++
 target-avr/cpugen/xsl/translate-inst.h.xsl | 118 ++++++++
 target-avr/cpugen/xsl/utils.xsl            | 108 +++++++
 10 files changed, 1220 insertions(+)
 create mode 100644 target-avr/cpugen/CMakeLists.txt
 create mode 100644 target-avr/cpugen/README.md
 create mode 100644 target-avr/cpugen/cpu/avr.yaml
 create mode 100644 target-avr/cpugen/src/CMakeLists.txt
 create mode 100644 target-avr/cpugen/src/cpugen.cpp
 create mode 100644 target-avr/cpugen/src/utils.cpp
 create mode 100644 target-avr/cpugen/src/utils.h
 create mode 100644 target-avr/cpugen/xsl/decode.c.xsl
 create mode 100644 target-avr/cpugen/xsl/translate-inst.h.xsl
 create mode 100644 target-avr/cpugen/xsl/utils.xsl

diff --git a/target-avr/cpugen/CMakeLists.txt b/target-avr/cpugen/CMakeLists.txt
new file mode 100644
index 0000000..ded391c
--- /dev/null
+++ b/target-avr/cpugen/CMakeLists.txt
@@ -0,0 +1,38 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(cpugen)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ggdb -g3")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+
+set(Boost_USE_STATIC_LIBS   ON)
+find_package(
+    Boost 1.60.0
+    REQUIRED
+    COMPONENTS
+        system
+        regex)
+#set(BUILD_SHARED_LIBS       OFF)
+#set(BUILD_STATIC_LIBS       ON)
+add_subdirectory(tinyxml2)
+add_subdirectory(yaml-cpp)
+
+include_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/..
+    ${CMAKE_CURRENT_SOURCE_DIR}/../yaml-cpp/include
+    ${Boost_INCLUDE_DIRS}
+)
+
+add_executable(
+    cpugen
+    src/cpugen.cpp
+    src/utils.cpp
+)
+
+target_link_libraries(
+    cpugen
+    yaml-cpp
+    tinyxml2
+    ${Boost_LIBRARIES}
+)
diff --git a/target-avr/cpugen/README.md b/target-avr/cpugen/README.md
new file mode 100644
index 0000000..f0caa8b
--- /dev/null
+++ b/target-avr/cpugen/README.md
@@ -0,0 +1,17 @@
+# CPUGEN
+## How to build
+within ```cpugen``` directory do
+```
+git clone https://github.com/leethomason/tinyxml2
+git clone https://github.com/jbeder/yaml-cpp
+mkdir build
+cd build
+cmake ..
+make
+```
+## How to use
+```
+cpugen ../cpu/avr.yaml
+xsltproc ../xsl/decode.c.xsl output.xml > ../../decode.c
+xsltproc ../xsl/translate-inst.h.xsl output.xml > ../../translate-inst.h
+```
diff --git a/target-avr/cpugen/cpu/avr.yaml b/target-avr/cpugen/cpu/avr.yaml
new file mode 100644
index 0000000..c36b628
--- /dev/null
+++ b/target-avr/cpugen/cpu/avr.yaml
@@ -0,0 +1,213 @@
+cpu:
+    name: avr
+    instructions:
+        - ADC:
+            opcode: 0001 11 hRr[1] Rd[5] lRr[4]
+        - ADD:
+            opcode: 0000 11 hRr[1] Rd[5] lRr[4]
+        - ADIW:
+            opcode: 1001 0110 hImm[2] Rd[2] lImm[4]
+        - AND:
+            opcode: 0010 00 hRr[1] Rd[5] lRr[4]
+        - ANDI:
+            opcode: 0111 hImm[4] Rd[4] lImm[4]
+        - ASR:
+            opcode: 1001 010 Rd[5] 0101
+        - BCLR:
+            opcode: 1001 0100 1 Bit[3] 1000
+        - BLD:
+            opcode: 1111 100 Rd[5] 0 Bit[3]
+        - BRBC:
+            opcode: 1111 01 Imm[7] Bit[3]
+        - BRBS:
+            opcode: 1111 00 Imm[7] Bit[3]
+        - BREAK:
+            opcode: 1001 0101 1001 1000
+        - BSET:
+            opcode: 1001 0100 0 Bit[3] 1000
+        - BST:
+            opcode: 1111 101 Rd[5] 0 Bit[3]
+        - CALL:
+            opcode: 1001 010 hImm[5] 111 lImm[17]
+        - CBI:
+            opcode: 1001 1000 Imm[5] Bit[3]
+        - COM:
+            opcode: 1001 010 Rd[5] 0000
+        - CP:
+            opcode: 0001 01 hRr[1] Rd[5] lRr[4]
+        - CPC:
+            opcode: 0000 01 hRr[1] Rd[5] lRr[4]
+        - CPI:
+            opcode: 0011 hImm[4] Rd[4] lImm[4]
+        - CPSE:
+            opcode: 0001 00 hRr[1] Rd[5] lRr[4]
+        - DEC:
+            opcode: 1001 010 Rd[5] 1010
+        - DES:
+            opcode: 1001 0100 Imm[4] 1011
+        - EICALL:
+            opcode: 1001 0101 0001 1001
+        - EIJMP:
+            opcode: 1001 0100 0001 1001
+        - ELPM1:
+            opcode: 1001 0101 1101 1000
+        - ELPM2:
+            opcode: 1001 000 Rd[5] 0110
+        - ELPMX:
+            opcode: 1001 000 Rd[5] 0111
+        - EOR:
+            opcode: 0010 01 hRr[1] Rd[5] lRr[4]
+        - FMUL:
+            opcode: 0000 0011 0 Rd[3] 1 Rr[3]
+        - FMULS:
+            opcode: 0000 0011 1 Rd[3] 0 Rr[3]
+        - FMULSU:
+            opcode: 0000 0011 1 Rd[3] 1 Rr[3]
+        - ICALL:
+            opcode: 1001 0101 0000 1001
+        - IJMP:
+            opcode: 1001 0100 0000 1001
+        - IN:
+            opcode: 1011 0 hImm[2] Rd[5] lImm[4]
+        - INC:
+            opcode: 1001 010 Rd[5] 0011
+        - JMP:
+            opcode: 1001 010 hImm[5] 110 lImm[17]
+        - LAC:
+            opcode: 1001 001 Rr[5] 0110
+        - LAS:
+            opcode: 1001 001 Rr[5] 0101
+        - LAT:
+            opcode: 1001 001 Rr[5] 0111
+        - LDX1:
+            opcode: 1001 000 Rd[5] 1100
+        - LDX2:
+            opcode: 1001 000 Rd[5] 1101
+        - LDX3:
+            opcode: 1001 000 Rd[5] 1110
+#        - LDY1:
+#            opcode: 1000 000 Rd[5] 1000
+        - LDY2:
+            opcode: 1001 000 Rd[5] 1001
+        - LDY3:
+            opcode: 1001 000 Rd[5] 1010
+        - LDDY:
+            opcode: 10 hImm[1] 0 mImm[2] 0 Rd[5] 1 lImm[3]
+#        - LDZ1:
+#            opcode: 1000 000 Rd[5] 0000
+        - LDZ2:
+            opcode: 1001 000 Rd[5] 0001
+        - LDZ3:
+            opcode: 1001 000 Rd[5] 0010
+        - LDDZ:
+            opcode: 10 hImm[1] 0 mImm[2] 0 Rd[5] 0 lImm[3]
+        - LDI:
+            opcode: 1110 hImm[4] Rd[4] lImm[4]
+        - LDS:
+            opcode: 1001 000 Rd[5] 0000 Imm[16]
+#        - LDS16:
+#            opcode: 1010 0 hImm[3] Rd[4] lImm[4]
+        - LPM1:
+            opcode: 1001 0101 1100 1000
+        - LPM2:
+            opcode: 1001 000 Rd[5] 0100
+        - LPMX:
+            opcode: 1001 000 Rd[5] 0101
+        - LSR:
+            opcode: 1001 010 Rd[5] 0110
+        - MOV:
+            opcode: 0010 11 hRr[1] Rd[5] lRr[4]
+        - MOVW:
+            opcode: 0000 0001 Rd[4] Rr[4]
+        - MUL:
+            opcode: 1001 11 hRr[1] Rd[5] lRr[4]
+        - MULS:
+            opcode: 0000 0010 Rd[4] Rr[4]
+        - MULSU:
+            opcode: 0000 0011 0 Rd[3] 0 Rr[3]
+        - NEG:
+            opcode: 1001 010 Rd[5] 0001
+        - NOP:
+            opcode: 0000 0000 0000 0000
+        - OR:
+            opcode: 0010 10 hRr[1] Rd[5] lRr[4]
+        - ORI:
+            opcode: 0110 hImm[4] Rd[4] lImm[4]
+        - OUT:
+            opcode: 1011 1 hImm[2] Rd[5] lImm[4]
+        - POP:
+            opcode: 1001 000 Rd[5] 1111
+        - PUSH:
+            opcode: 1001 001 Rd[5] 1111
+        - RCALL:
+            opcode: 1101 Imm[12]
+        - RET:
+            opcode: 1001 0101 0000 1000
+        - RETI:
+            opcode: 1001 0101 0001 1000
+        - RJMP:
+            opcode: 1100 Imm[12]
+        - ROR:
+            opcode: 1001 010 Rd[5] 0111
+        - SBC:
+            opcode: 0000 10 hRr[1] Rd[5] lRr[4]
+        - SBCI:
+            opcode: 0100 hImm[4] Rd[4] lImm[4]
+        - SBI:
+            opcode: 1001 1010 Imm[5] Bit[3]
+        - SBIC:
+            opcode: 1001 1001 Imm[5] Bit[3]
+        - SBIS:
+            opcode: 1001 1011 Imm[5] Bit[3]
+        - SBIW:
+            opcode: 1001 0111 hImm[2] Rd[2] lImm[4]
+#        - SBR:
+#            opcode: 0110 hImm[4] Rd[4] lImm[4]
+        - SBRC:
+            opcode: 1111 110 Rr[5] 0 Bit[3]
+        - SBRS:
+            opcode: 1111 111 Rr[5] 0 Bit[3]
+        - SLEEP:
+            opcode: 1001 0101 1000 1000
+        - SPM:
+            opcode: 1001 0101 1110 1000
+        - SPMX:
+            opcode: 1001 0101 1111 1000
+        - STX1:
+            opcode: 1001 001 Rr[5] 1100
+        - STX2:
+            opcode: 1001 001 Rr[5] 1101
+        - STX3:
+            opcode: 1001 001 Rr[5] 1110
+#        - STY1:
+#            opcode: 1000 001 Rd[5] 1000
+        - STY2:
+            opcode: 1001 001 Rd[5] 1001
+        - STY3:
+            opcode: 1001 001 Rd[5] 1010
+        - STDY:
+            opcode: 10 hImm[1] 0 mImm[2] 1 Rd[5] 1 lImm[3]
+#        - STZ1:
+#            opcode: 1000 001 Rd[5] 0000
+        - STZ2:
+            opcode: 1001 001 Rd[5] 0001
+        - STZ3:
+            opcode: 1001 001 Rd[5] 0010
+        - STDZ:
+            opcode: 10 hImm[1] 0 mImm[2] 1 Rd[5] 0 lImm[3]
+        - STS:
+            opcode: 1001 001 Rd[5] 0000 Imm[16]
+#        - STS16:
+#            opcode: 1010 1 hImm[3] Rd[4] lImm[4]
+        - SUB:
+            opcode: 0001 10 hRr[1] Rd[5] lRr[4]
+        - SUBI:
+            opcode: 0101 hImm[4] Rd[4] lImm[4]
+        - SWAP:
+            opcode: 1001 010 Rd[5] 0010
+#        - TST:
+#            opcode: 0010 00 Rd[10]
+        - WDR:
+            opcode: 1001 0101 1010 1000
+        - XCH:
+            opcode: 1001 001 Rd[5] 0100
diff --git a/target-avr/cpugen/src/CMakeLists.txt b/target-avr/cpugen/src/CMakeLists.txt
new file mode 100644
index 0000000..5f08761
--- /dev/null
+++ b/target-avr/cpugen/src/CMakeLists.txt
@@ -0,0 +1,62 @@
+#
+# CPUGEN
+#
+# Copyright (c) 2016 Michael Rolnik
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+cmake_minimum_required(VERSION 2.8)
+
+project(cpugen)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ggdb -g3")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+
+set(Boost_USE_STATIC_LIBS   ON)
+find_package(
+    Boost 1.60.0
+    REQUIRED
+    COMPONENTS
+        system
+        regex)
+set(BUILD_SHARED_LIBS       OFF)
+set(BUILD_STATIC_LIBS       ON)
+add_subdirectory(../tinyxml2    ${CMAKE_CURRENT_BINARY_DIR}/tinyxml2)
+add_subdirectory(../yaml-cpp    ${CMAKE_CURRENT_BINARY_DIR}/yaml-cpp)
+
+include_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/..
+    ${CMAKE_CURRENT_SOURCE_DIR}/../yaml-cpp/include
+    ${Boost_INCLUDE_DIRS}
+)
+
+add_executable(
+    cpugen
+    cpugen.cpp
+    utils.cpp
+)
+
+target_link_libraries(
+    cpugen
+    yaml-cpp
+    tinyxml2_static
+    ${Boost_LIBRARIES}
+)
diff --git a/target-avr/cpugen/src/cpugen.cpp b/target-avr/cpugen/src/cpugen.cpp
new file mode 100644
index 0000000..e479b08
--- /dev/null
+++ b/target-avr/cpugen/src/cpugen.cpp
@@ -0,0 +1,457 @@
+/*
+ * CPUGEN
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <limits>
+#include <stdint.h>
+#include <algorithm>
+#include <iomanip>
+#include <string>
+#include <vector>
+#include <boost/regex.hpp>
+
+#include "yaml-cpp/yaml.h"
+#include "tinyxml2/tinyxml2.h"
+
+#include "utils.h"
+
+#include <boost/algorithm/string.hpp>
+
+struct  inst_info_t {
+    std::string name;
+    std::string opcode;
+
+    tinyxml2::XMLElement *nodeFields;
+};
+
+struct  cpu_info_t {
+    std::string name;
+    std::vector<inst_info_t * > instructions;
+};
+
+int countbits(uint64_t value)
+{
+    int counter = 0;
+    uint64_t mask = 1;
+
+    for (size_t i = 0; i < sizeof(value) * 8; ++i) {
+        if (value & mask) {
+            counter++;
+        }
+
+        mask <<= 1;
+    }
+
+    return counter;
+}
+
+int encode(uint64_t mask, uint64_t value)
+{
+    uint64_t i = 0x0000000000000001;
+    uint64_t j = 0x0000000000000001;
+    uint64_t v = 0x0000000000000000;
+
+    for (size_t it = 0; it < sizeof(value) * 8; ++it) {
+        if (mask & i) {
+            if (value & j) {
+                v |= i;
+            }
+            j <<= 1;
+        }
+
+        i <<= 1;
+    }
+
+    return v;
+}
+
+std::string num2hex(uint64_t value)
+{
+    std::ostringstream  str;
+    str << "0x" << std::hex << std::setw(8) << std::setfill('0') << value;
+
+    return str.str();
+}
+
+tinyxml2::XMLDocument   doc;
+
+void operator >> (const YAML::Node & node, inst_info_t & info)
+{
+    for (auto it = node.begin(); it != node.end(); ++it) {
+        const YAML::Node & curr = it->second;
+        std::string name = it->first.as<std::string>();
+
+        info.opcode = curr["opcode"].as<std::string>();
+
+        const char *response;
+        std::vector<std::string> fields;
+        std::string opcode = "";
+        int offset;
+        tinyxml2::XMLElement *nodeFields = doc.NewElement("fields");
+        uint32_t bitoffset = 0;
+
+        do {
+            opcode = info.opcode;
+            boost::replace_all(info.opcode, "  ", " ");
+            boost::replace_all(info.opcode, "0 0", "00");
+            boost::replace_all(info.opcode, "0 1", "01");
+            boost::replace_all(info.opcode, "1 0", "10");
+            boost::replace_all(info.opcode, "1 1", "11");
+        } while (opcode != info.opcode);
+
+        boost::replace_all(info.opcode, "- -", "--");
+
+        fields = boost::split(fields, info.opcode, boost::is_any_of(" "));
+
+        opcode = "";
+        info.opcode = "";
+        unsigned f = 0;
+        for (int i = 0; i < fields.size(); i++) {
+            std::string field = fields[i];
+
+            if (field.empty()) {
+                continue;
+            }
+
+            size_t len = field.length();
+            boost::cmatch match;
+            tinyxml2::XMLElement *nodeField = doc.NewElement("field");
+
+            nodeFields->LinkEndChild(nodeField);
+
+            if (boost::regex_match(field.c_str(),
+                        match,
+                        boost::regex("^[01]+$"))) {
+                int length = field.length();
+
+                nodeField->SetAttribute("name", field.c_str());
+                nodeField->SetAttribute("length", length);
+                nodeField->SetAttribute("offset", bitoffset);
+
+                info.opcode += field;
+
+                bitoffset   += len;
+            } else if (boost::regex_match(
+                    field.c_str(),
+                    match,
+                    boost::regex("^[-]+$")))
+            {
+                int         length = field.length();
+
+                nodeField->SetAttribute("name", "RESERVED");
+                nodeField->SetAttribute("length", length);
+                nodeField->SetAttribute("offset", bitoffset);
+
+                info.opcode += field;
+
+                bitoffset   += len;
+            } else if (boost::regex_match(field.c_str(),
+                    match,
+                    boost::regex("^([a-zA-Z][a-zA-Z0-9]*)\\[([0-9]+)\\]"))) {
+                int         length = std::atoi(match[2].first);
+                std::string name = std::string(match[1].first, match[1].second);
+
+                nodeField->SetAttribute("name", name.c_str());
+                nodeField->SetAttribute("length", length);
+                nodeField->SetAttribute("offset", bitoffset);
+
+                for (int j = 0; j < length; j++) {
+                    info.opcode += 'a' + f;
+                }
+
+                f++;
+
+                bitoffset   += length;
+            } else if (field == "~") {
+                /* nothing */
+            } else {
+                std::cout << "cannot parse " << name
+                          << ": '" << field << "'" << std::endl;
+                exit(0);
+            }
+        }
+
+        info.nodeFields = nodeFields;
+        info.name = name;
+    }
+}
+
+void operator >> (inst_info_t & info, tinyxml2::XMLElement & node)
+{
+    node.SetAttribute("length", (unsigned)info.opcode.length());
+    node.SetAttribute("name", info.name.c_str());
+    node.SetAttribute("opcode", info.opcode.c_str());
+}
+
+void operator >> (const YAML::Node & node, cpu_info_t & cpu)
+{
+    const YAML::Node & insts = node["instructions"];
+
+    cpu.name = node["name"].as<std::string>();
+
+    for (unsigned i = 0; i < insts.size(); i++) {
+        inst_info_t *inst = new inst_info_t();
+
+        insts[i] >> (*inst);
+
+        if (inst->opcode != "" &&inst->opcode != "~") {
+            cpu.instructions.push_back(inst);
+        }
+    }
+}
+
+std::pair<size_t, size_t> getMinMaxInstructionLength(
+                                std::vector<inst_info_t * > &instructions)
+{
+    size_t  min = std::numeric_limits<size_t>::max();
+    size_t  max = std::numeric_limits<size_t>::min();
+
+    for (size_t i = 0; i < instructions.size(); i++) {
+        inst_info_t *inst = instructions[i];
+        std::string opcode = inst->opcode;
+        size_t length = opcode.length();
+
+        if (opcode != "~") {
+            min = std::min(min, length);
+            max = std::max(max, length);
+        }
+    }
+
+    return std::make_pair(min, max);
+}
+
+uint64_t getXs(std::string const &opcode, size_t len, char chr)
+{
+    uint64_t result = 0;
+    size_t cur;
+    uint64_t bit = 1ull << (len - 1);
+
+    for (cur = 0; cur < len; cur++) {
+        if (opcode[cur] == chr) {
+            result  |= bit;
+        }
+
+        bit >>= 1;
+    }
+
+    return result;
+}
+
+uint64_t get0s(std::string const &opcode, size_t len)
+{
+    return getXs(opcode, len, '0');
+}
+
+uint64_t get1s(std::string const &opcode, size_t len)
+{
+    return getXs(opcode, len, '1');
+}
+
+class InstSorter
+{
+    public:
+        InstSorter(size_t offset, size_t length)
+            : offset(offset), length(length)
+        {
+
+        }
+
+        bool operator()(inst_info_t *a, inst_info_t *b)
+        {
+            uint64_t field0;
+            uint64_t field1;
+            uint64_t fieldA;
+            uint64_t fieldB;
+
+            field0 = get0s(a->opcode, length);
+            field1 = get1s(a->opcode, length);
+            fieldA = field0 | field1;
+
+            field0 = get0s(b->opcode, length);
+            field1 = get1s(b->opcode, length);
+            fieldB = field0 | field1;
+
+            return fieldB < fieldA;
+        }
+
+    private:
+        size_t offset;
+        size_t length;
+
+};
+
+void divide(uint64_t select0, uint64_t select1,
+            std::vector<inst_info_t * > &info,
+            size_t level, tinyxml2::XMLElement *root)
+{
+    std::pair<size_t, size_t>   minmaxSize;
+
+    minmaxSize = getMinMaxInstructionLength(info);
+
+    size_t minlen = minmaxSize.first;
+    size_t maxlen = minmaxSize.second;
+    size_t bits = std::min(minlen, sizeof(select0) * 8);
+    uint64_t all1 = (1ULL << bits) - 1;
+    uint64_t all0 = (1ULL << bits) - 1;
+    uint64_t allx = (1ULL << bits) - 1;
+    uint64_t diff;
+
+    for (size_t i = 0; i < info.size(); ++i) {
+        std::string opcode = info[i]->opcode;
+        uint64_t field0 = get0s(opcode, minlen);
+        uint64_t field1 = get1s(opcode, minlen);
+        uint64_t fieldx = field0 | field1;
+
+        if (opcode == "~") {
+            continue;
+        }
+        all0 &= field0;
+        all1 &= field1;
+        allx &= fieldx;
+    }
+
+    diff = allx ^ (all0 | all1);
+
+    if (diff == 0) {
+        tinyxml2::XMLElement *oopsNode = doc.NewElement("oops");
+        oopsNode->SetAttribute("bits", (unsigned)bits);
+        oopsNode->SetAttribute("maxlen", (unsigned)maxlen);
+        oopsNode->SetAttribute("allx", num2hex(allx).c_str());
+        oopsNode->SetAttribute("all0", num2hex(all0).c_str());
+        oopsNode->SetAttribute("all1", num2hex(all1).c_str());
+        oopsNode->SetAttribute("select0", num2hex(select0).c_str());
+        oopsNode->SetAttribute("select1", num2hex(select1).c_str());
+        root->LinkEndChild(oopsNode);
+
+        std::sort(info.begin(), info.end(), InstSorter(0, minlen));
+
+        for (size_t i = 0; i < info.size(); ++i) {
+            inst_info_t *inst = info[i];
+            tinyxml2::XMLElement *instNode = doc.NewElement("instruction");
+            tinyxml2::XMLElement *matchNode = doc.NewElement("match01");
+
+            uint64_t field0 = get0s(inst->opcode, minlen);
+            uint64_t field1 = get1s(inst->opcode, minlen);
+            uint64_t fieldx = field0 | field1;
+
+            root->LinkEndChild(matchNode);
+            matchNode->LinkEndChild(instNode);
+
+            matchNode->SetAttribute("mask", num2hex(fieldx).c_str());
+            matchNode->SetAttribute("value", num2hex(field1).c_str());
+
+            *inst >> *instNode;
+
+            instNode->LinkEndChild(inst->nodeFields);
+        }
+
+        return;
+    }
+
+    uint64_t    bitsN = countbits(diff); /* number of meaningfull bits */
+
+    tinyxml2::XMLElement *switchNode = doc.NewElement("switch");
+    switchNode->SetAttribute("bits", (unsigned)bits);
+    switchNode->SetAttribute("bitoffset", (unsigned)0);
+    switchNode->SetAttribute("mask", num2hex(diff).c_str());
+    root->LinkEndChild(switchNode);
+
+    /* there are at most 1 << length subsets */
+    for (size_t s = 0; s < (1 << bitsN); ++s) {
+        std::vector<inst_info_t * > subset;
+        uint64_t index = encode(diff, s);
+
+        tinyxml2::XMLElement *caseNode = doc.NewElement("case");
+        caseNode->SetAttribute("value", num2hex(index).c_str());
+        switchNode->LinkEndChild(caseNode);
+
+        for (size_t i = 0; i < info.size(); ++i) {
+            std::string opcode = info[i]->opcode;
+            uint64_t field0 = get0s(opcode, minlen);
+            uint64_t field1 = get1s(opcode, minlen);
+
+            if (((field0 & diff) == (~index & diff))
+                && ((field1 & diff) == (index  & diff))) {
+                subset.push_back(info[i]);
+            }
+        }
+
+        if (subset.size() == 1) {
+            inst_info_t *inst = subset[0];
+            tinyxml2::XMLElement *instNode = doc.NewElement("instruction");
+
+            *inst >> *instNode;
+
+            instNode->LinkEndChild(inst->nodeFields);
+
+            caseNode->LinkEndChild(instNode);
+        } else if (subset.size() > 1) {
+            /* this is a set of instructions, continue dividing */
+            divide(select0 | (diff & ~index),
+                   select1 | (diff & index),
+                   subset,
+                   level + 2,
+                   caseNode);
+        }
+    }
+}
+
+void generateParser(cpu_info_t & cpu)
+{
+    tinyxml2::XMLElement *cpuNode = doc.NewElement("cpu");
+    tinyxml2::XMLElement *instNode = doc.NewElement("instructions");
+
+    cpuNode->SetAttribute("name", cpu.name.c_str());
+    cpuNode->LinkEndChild(instNode);
+
+    doc.LinkEndChild(cpuNode);
+
+    divide(0, 0, cpu.instructions, 1, instNode);
+
+    doc.SaveFile("output.xml");
+}
+
+int main(int argc, char *argv[])
+{
+    if (argc != 2) {
+        std::cerr << "error: usage: cpuarg [input.yaml]" << std::endl;
+        std::exit(0);
+    }
+
+    try {
+        const char *filename = argv[1];
+        std::ifstream input(filename);
+        YAML::Node doc = YAML::Load(input);
+        cpu_info_t cpu;
+
+        doc["cpu"] >> cpu;
+
+        generateParser(cpu);
+    } catch(const YAML::Exception & e) {
+        std::cerr << e.what() << "\n";
+    }
+}
diff --git a/target-avr/cpugen/src/utils.cpp b/target-avr/cpugen/src/utils.cpp
new file mode 100644
index 0000000..5ef1961
--- /dev/null
+++ b/target-avr/cpugen/src/utils.cpp
@@ -0,0 +1,26 @@
+/*
+ * CPUGEN
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "utils.h"
+#include <sstream>
diff --git a/target-avr/cpugen/src/utils.h b/target-avr/cpugen/src/utils.h
new file mode 100644
index 0000000..0efaa3e
--- /dev/null
+++ b/target-avr/cpugen/src/utils.h
@@ -0,0 +1,78 @@
+/*
+ * CPUGEN
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <iomanip>
+
+typedef std::vector<std::string>    string_vector_t;
+
+std::string extract(std::string & str, std::string delimiter);
+std::string rextract(std::string & str, std::string del);
+string_vector_t split(std::string str, std::string delimeter);
+std::string join(string_vector_t const &vec, std::string delimeter);
+
+int countbits(uint64_t value);
+int encode(uint64_t mask, uint64_t value);
+std::string num2hex(uint64_t value);
+
+class multi
+{
+/*
+    http://www.angelikalanger.com/Articles/Cuj/05.Manipulators/Manipulators.html
+*/
+    public:
+        multi(char c, size_t n)
+            : how_many_(n)
+            , what_(c)
+        {
+        }
+
+    private:
+        const size_t    how_many_;
+        const char      what_;
+
+    public:
+        template <class Ostream>
+        Ostream & apply(Ostream & os) const
+        {
+            for (unsigned int i = 0; i < how_many_; ++i) {
+                os.put(what_);
+            }
+            os.flush();
+            return os;
+        }
+};
+
+template <class Ostream>
+Ostream & operator << (Ostream & os, const multi & m)
+{
+    return m.apply(os);
+}
+
+#endif
diff --git a/target-avr/cpugen/xsl/decode.c.xsl b/target-avr/cpugen/xsl/decode.c.xsl
new file mode 100644
index 0000000..b8aa02c
--- /dev/null
+++ b/target-avr/cpugen/xsl/decode.c.xsl
@@ -0,0 +1,103 @@
+<?xml version="1.0"?>
+<!--
+   CPUGEN
+
+   Copyright (c) 2016 Michael Rolnik
+
+   Permission is hereby granted, free of charge, to any person obtaining a copy
+   of this software and associated documentation files (the "Software"), to deal
+   in the Software without restriction, including without limitation the rights
+   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+   copies of the Software, and to permit persons to whom the Software is
+   furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+   THE SOFTWARE.
+-->
+
+<xsl:stylesheet version="1.0"
+    xmlns:xsl   = "http://www.w3.org/1999/XSL/Transform"
+    xmlns:func  = "http://exslt.org/functions"
+    xmlns:str   = "http://exslt.org/strings"
+    xmlns:mine  = "mrolnik@gmail.com"
+    extension-element-prefixes="func"
+    >
+
+    <xsl:strip-space elements="*"/>
+    <xsl:output method="text" omit-xml-declaration="yes" indent="yes"/>
+
+    <xsl:include href="utils.xsl"/>
+
+    <xsl:template match="/cpu/instructions">
+        <xsl:value-of select="$license" />
+        <xsl:text>
+#include &lt;stdint.h&gt;
+#include "translate.h"
+
+void </xsl:text><xsl:value-of select="/cpu/@name"/><xsl:text>_decode(uint32_t pc, uint32_t *l, uint32_t c, translate_function_t *t)
+{
+</xsl:text>
+    <xsl:apply-templates select="switch">
+        <xsl:with-param name="ident" ><xsl:value-of select="$tab"/></xsl:with-param>
+    </xsl:apply-templates>
+<xsl:text>
+}
+</xsl:text>
+</xsl:template>
+
+    <xsl:template match="switch">
+        <xsl:param name="ident" />
+        <xsl:if test="not (@bitoffset = ../../@bitoffset and @bits = ../../@bits)" >
+            <xsl:value-of select="concat($ident, 'uint32_t opc  = extract32(c, ', @bitoffset, ', ', @bits, ');', $newline)" />
+        </xsl:if>
+        <xsl:value-of select="concat($ident, 'switch (opc &amp; ', @mask, ') {', $newline)"/>
+        <xsl:apply-templates select="case">
+            <xsl:with-param name="ident" ><xsl:value-of select="$ident"/><xsl:value-of select="$tab"/></xsl:with-param>
+        </xsl:apply-templates>
+        <xsl:value-of select="concat($ident, '}', $newline)"/>
+    </xsl:template>
+
+    <xsl:template match="case">
+        <xsl:param name="ident" />
+
+        <xsl:value-of select="concat($ident, 'case ', @value, ': {', $newline)"/>
+        <xsl:apply-templates select="switch">
+            <xsl:with-param name="ident"><xsl:value-of select="concat($ident, $tab)"/></xsl:with-param>
+        </xsl:apply-templates>
+        <xsl:apply-templates select="match01">
+            <xsl:with-param name="ident"><xsl:value-of select="concat($ident, $tab)"/></xsl:with-param>
+        </xsl:apply-templates>
+        <xsl:apply-templates select="instruction">
+            <xsl:with-param name="ident"><xsl:value-of select="concat($ident, $tab)"/></xsl:with-param>
+        </xsl:apply-templates>
+        <xsl:value-of select="concat($ident, $tab, 'break;', $newline)"/>
+        <xsl:value-of select="concat($ident, '}', $newline)"/>
+    </xsl:template>
+
+    <xsl:template match="instruction">
+        <xsl:param name="ident" />
+
+        <xsl:value-of select="concat($ident, '*l = ', string-length(@opcode), ';', $newline)" />
+        <xsl:value-of select="concat($ident, '*t = &amp;', /cpu/@name, '_translate_', @name, ';', $newline)" />
+    </xsl:template>
+
+    <xsl:template match="match01">
+        <xsl:param name="ident" />
+
+        <xsl:value-of select="concat($ident, 'if((opc &amp; ', @mask, ' == ', @value, ') {', $newline)" />
+        <xsl:apply-templates select="instruction">
+            <xsl:with-param name="ident"><xsl:value-of select="concat($ident, $tab)"/></xsl:with-param>
+        </xsl:apply-templates>
+        <xsl:value-of select="concat($ident, 'break;', $newline)"/>
+        <xsl:value-of select="concat($ident, '}', $newline)"/>
+    </xsl:template>
+
+</xsl:stylesheet>
diff --git a/target-avr/cpugen/xsl/translate-inst.h.xsl b/target-avr/cpugen/xsl/translate-inst.h.xsl
new file mode 100644
index 0000000..2830ce3
--- /dev/null
+++ b/target-avr/cpugen/xsl/translate-inst.h.xsl
@@ -0,0 +1,118 @@
+<?xml version="1.0"?>
+
+<!--
+   CPUGEN
+
+   Copyright (c) 2016 Michael Rolnik
+
+   Permission is hereby granted, free of charge, to any person obtaining a copy
+   of this software and associated documentation files (the "Software"), to deal
+   in the Software without restriction, including without limitation the rights
+   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+   copies of the Software, and to permit persons to whom the Software is
+   furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+   THE SOFTWARE.
+-->
+
+<xsl:stylesheet version="1.0"
+    xmlns:xsl   = "http://www.w3.org/1999/XSL/Transform"
+    xmlns:func  = "http://exslt.org/functions"
+    xmlns:str   = "http://exslt.org/strings"
+    xmlns:mine  = "mrolnik@gmail.com"
+    extension-element-prefixes="func"
+    >
+
+    <xsl:include href="utils.xsl"/>
+
+<xsl:strip-space elements="*"/>
+<xsl:output method="text" omit-xml-declaration="yes" indent="yes"/>
+
+<xsl:template match="/cpu/instructions">
+        <xsl:value-of select="$license" />
+<xsl:text>
+#ifndef AVR_TRANSLATE_INST_H_
+#define AVR_TRANSLATE_INST_H_
+
+typedef struct DisasContext    DisasContext;
+
+</xsl:text>
+
+<xsl:apply-templates select="//instruction" />
+
+<xsl:text>
+#endif
+</xsl:text>
+</xsl:template>
+
+<xsl:template match="instruction">
+    <xsl:variable name="length"     select="string-length(@opcode)" />
+    <xsl:variable name="datatype"   select="mine:get-opcode-struct-type($length)" />
+    <xsl:variable name="namestem"   select="@name"/>
+    <xsl:variable name="ilength"    select="@length"/>
+
+    <xsl:value-of select="concat('int ', /cpu/@name, '_translate_', @name, '(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);', $newline)" />
+    <xsl:for-each select="fields/field">
+        <xsl:sort select="position()" data-type="number" order="descending"/>
+        <xsl:choose>
+            <xsl:when test="str:replace(str:replace(@name, '0', ''), '1', '') = ''">
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:variable name="field" select="substring(@name, 2, string-length(@name) - 1)" />
+                <xsl:variable name="h"     select="../field[@name = concat('h', $field)]"/>
+                <xsl:variable name="l"     select="../field[@name = concat('l', $field)]"/>
+                <xsl:variable name="m"     select="../field[@name = concat('m', $field)]"/>
+
+                <xsl:if test="not($h/@name = @name or $m/@name = @name or $l/@name = @name)">
+                    <xsl:value-of select="concat('static inline uint32_t ', $namestem, '_', @name, '(uint32_t opcode)', $newline)" />
+                    <xsl:value-of select="concat('{', $newline)" />
+                    <xsl:value-of select="concat('    return extract32(opcode, ', $ilength - @offset - @length, ', ', @length, ');', $newline)" />
+                    <xsl:value-of select="concat('}', $newline)" />
+                </xsl:if>
+
+                <xsl:if test="$l and $h and ($h/@name = @name)">
+                    <xsl:value-of select="concat('static inline uint32_t ', $namestem, '_', $field, '(uint32_t opcode)', $newline)" />
+                    <xsl:value-of select="concat('{', $newline)" />
+                    <xsl:value-of select="'    return '" />
+
+<xsl:variable name="l_length"   select="$l/@length"/>
+<xsl:variable name="l_offset"   select="$ilength - $l/@offset - $l_length"/>
+
+<xsl:variable name="m_length"   select="$m/@length"/>
+<xsl:variable name="m_offset"   select="$ilength - $m/@offset - $m_length"/>
+
+<xsl:variable name="h_length"   select="$h/@length"/>
+<xsl:variable name="h_offset"   select="$ilength - $h/@offset - $h_length"/>
+
+
+                    <xsl:choose>
+                        <xsl:when test="$h and $m and $l">
+                            <xsl:value-of select="concat('(extract32(opcode, ', $h_offset, ', ', $h_length, ') &lt;&lt; ', $l_length + $m_length, ') | ')" />
+                            <xsl:value-of select="concat('(extract32(opcode, ', $m_offset, ', ', $m_length, ') &lt;&lt; ', $l_length, ') | ')" />
+                            <xsl:value-of select="concat('(extract32(opcode, ', $l_offset, ', ', $l_length, '))')" />
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <xsl:value-of select="concat('(extract32(opcode, ', $h_offset, ', ', $h_length, ') &lt;&lt; ', $l_length, ') | ')" />
+                            <xsl:value-of select="concat('(extract32(opcode, ', $l_offset, ', ', $l_length, '))')" />
+                        </xsl:otherwise>
+                    </xsl:choose>
+
+                    <xsl:value-of select="concat(';', $newline)"/>
+                    <xsl:value-of select="concat('}', $newline)"/>
+                </xsl:if>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:for-each>
+    <xsl:value-of select="$newline" />
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/target-avr/cpugen/xsl/utils.xsl b/target-avr/cpugen/xsl/utils.xsl
new file mode 100644
index 0000000..b4511b6
--- /dev/null
+++ b/target-avr/cpugen/xsl/utils.xsl
@@ -0,0 +1,108 @@
+<?xml version="1.0"?>
+<!--
+   CPUGEN
+
+   Copyright (c) 2016 Michael Rolnik
+
+   Permission is hereby granted, free of charge, to any person obtaining a copy
+   of this software and associated documentation files (the "Software"), to deal
+   in the Software without restriction, including without limitation the rights
+   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+   copies of the Software, and to permit persons to whom the Software is
+   furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+   THE SOFTWARE.
+-->
+<xsl:stylesheet version="1.0"
+    xmlns:xsl   = "http://www.w3.org/1999/XSL/Transform"
+    xmlns:str   = "http://exslt.org/strings"
+    xmlns:func  = "http://exslt.org/functions"
+    xmlns:exsl  = "http://exslt.org/common"
+    xmlns:mine  = "mrolnik@gmail.com"
+    extension-element-prefixes="func">
+
+    <xsl:output method = "text" />
+    <xsl:strip-space elements="*"/>
+
+    <xsl:variable name="newline">
+    <xsl:text>
+</xsl:text>
+    </xsl:variable>
+    <xsl:variable name="license">
+        <xsl:text>/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * &lt;http://www.gnu.org/licenses/lgpl-2.1.html&gt;
+ */
+
+</xsl:text>
+    </xsl:variable>
+
+    <xsl:variable name="tab">
+        <xsl:text>    </xsl:text>
+    </xsl:variable>
+
+    <func:function name="mine:pad" as="string">
+        <xsl:param      name="str"      as="xs:string"/>
+        <xsl:param      name="len"      as="xs:integer"/>
+        <xsl:variable   name="lstr"     select="string-length($str)"/>
+        <xsl:variable   name="pad"      select="str:padding($len - $lstr, ' ')"/>
+        <func:result select="concat($str,$pad)"/>
+    </func:function>
+
+    <func:function  name="mine:toupper" as="string">
+        <xsl:param      name="str"      as="xs:string"/>
+        <xsl:variable   name="upper"    select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ ,-.'" />
+        <xsl:variable   name="lower"    select="'abcdefghijklmnopqrstuvwxyz____'" />
+        <func:result    select="translate($str, $upper, $lower)" />
+    </func:function>
+
+    <func:function  name="mine:toname" as="string">
+        <xsl:param      name="str"      as="xs:string"/>
+        <xsl:variable   name="src"      select="'. ,-'" />
+        <xsl:variable   name="dst"      select="'_'" />
+        <func:result    select="translate($str, $src, $dst)" />
+    </func:function>
+
+    <func:function name="mine:get-opcode-struct-type">
+        <xsl:param name="length"/>
+            <xsl:choose>
+                <xsl:when test="$length &lt; '9'">
+                    <func:result select="'uint8_t '"/>
+                </xsl:when>
+                <xsl:when test="$length &lt; '17'">
+                    <func:result select="'uint16_t'"/>
+                </xsl:when>
+                <xsl:when test="$length &lt; '33'">
+                    <func:result select="'uint32_t'"/>
+                </xsl:when>
+                <xsl:when test="$length &lt; '65'">
+                    <func:result select="'uint64_t'"/>
+                </xsl:when>
+            </xsl:choose>
+    </func:function>
+
+</xsl:stylesheet>
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 09/13] target-avr: adding instruction decoder
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (7 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 08/13] target-avr: instruction decoder generator Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 10/13] target-avr: Put env pointer in DisasContext Richard Henderson
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

From: Michael Rolnik <mrolnik@gmail.com>

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Message-Id: <1471522070-77598-10-git-send-email-mrolnik@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/Makefile.objs |   1 +
 target-avr/decode.c      | 691 +++++++++++++++++++++++++++++++++++++++++++++++
 target-avr/translate.c   |   2 +
 3 files changed, 694 insertions(+)
 create mode 100644 target-avr/decode.c

diff --git a/target-avr/Makefile.objs b/target-avr/Makefile.objs
index a448792..9848b1c 100644
--- a/target-avr/Makefile.objs
+++ b/target-avr/Makefile.objs
@@ -21,4 +21,5 @@
 obj-y += translate.o cpu.o helper.o
 obj-y += gdbstub.o
 obj-y += translate-inst.o
+obj-y += decode.o
 obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-avr/decode.c b/target-avr/decode.c
new file mode 100644
index 0000000..2d2e54e
--- /dev/null
+++ b/target-avr/decode.c
@@ -0,0 +1,691 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include <stdint.h>
+#include "translate.h"
+
+void avr_decode(uint32_t pc, uint32_t *l, uint32_t c, translate_function_t *t)
+{
+    uint32_t opc = extract32(c, 0, 16);
+    switch (opc & 0x0000d000) {
+        case 0x00000000: {
+            switch (opc & 0x00002c00) {
+                case 0x00000000: {
+                    switch (opc & 0x00000300) {
+                        case 0x00000000: {
+                            *l = 16;
+                            *t = &avr_translate_NOP;
+                            break;
+                        }
+                        case 0x00000100: {
+                            *l = 16;
+                            *t = &avr_translate_MOVW;
+                            break;
+                        }
+                        case 0x00000200: {
+                            *l = 16;
+                            *t = &avr_translate_MULS;
+                            break;
+                        }
+                        case 0x00000300: {
+                            switch (opc & 0x00000088) {
+                                case 0x00000000: {
+                                    *l = 16;
+                                    *t = &avr_translate_MULSU;
+                                    break;
+                                }
+                                case 0x00000008: {
+                                    *l = 16;
+                                    *t = &avr_translate_FMUL;
+                                    break;
+                                }
+                                case 0x00000080: {
+                                    *l = 16;
+                                    *t = &avr_translate_FMULS;
+                                    break;
+                                }
+                                case 0x00000088: {
+                                    *l = 16;
+                                    *t = &avr_translate_FMULSU;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case 0x00000400: {
+                    *l = 16;
+                    *t = &avr_translate_CPC;
+                    break;
+                }
+                case 0x00000800: {
+                    *l = 16;
+                    *t = &avr_translate_SBC;
+                    break;
+                }
+                case 0x00000c00: {
+                    *l = 16;
+                    *t = &avr_translate_ADD;
+                    break;
+                }
+                case 0x00002000: {
+                    *l = 16;
+                    *t = &avr_translate_AND;
+                    break;
+                }
+                case 0x00002400: {
+                    *l = 16;
+                    *t = &avr_translate_EOR;
+                    break;
+                }
+                case 0x00002800: {
+                    *l = 16;
+                    *t = &avr_translate_OR;
+                    break;
+                }
+                case 0x00002c00: {
+                    *l = 16;
+                    *t = &avr_translate_MOV;
+                    break;
+                }
+            }
+            break;
+        }
+        case 0x00001000: {
+            switch (opc & 0x00002000) {
+                case 0x00000000: {
+                    switch (opc & 0x00000c00) {
+                        case 0x00000000: {
+                            *l = 16;
+                            *t = &avr_translate_CPSE;
+                            break;
+                        }
+                        case 0x00000400: {
+                            *l = 16;
+                            *t = &avr_translate_CP;
+                            break;
+                        }
+                        case 0x00000800: {
+                            *l = 16;
+                            *t = &avr_translate_SUB;
+                            break;
+                        }
+                        case 0x00000c00: {
+                            *l = 16;
+                            *t = &avr_translate_ADC;
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case 0x00002000: {
+                    *l = 16;
+                    *t = &avr_translate_CPI;
+                    break;
+                }
+            }
+            break;
+        }
+        case 0x00004000: {
+            switch (opc & 0x00002000) {
+                case 0x00000000: {
+                    *l = 16;
+                    *t = &avr_translate_SBCI;
+                    break;
+                }
+                case 0x00002000: {
+                    *l = 16;
+                    *t = &avr_translate_ORI;
+                    break;
+                }
+            }
+            break;
+        }
+        case 0x00005000: {
+            switch (opc & 0x00002000) {
+                case 0x00000000: {
+                    *l = 16;
+                    *t = &avr_translate_SUBI;
+                    break;
+                }
+                case 0x00002000: {
+                    *l = 16;
+                    *t = &avr_translate_ANDI;
+                    break;
+                }
+            }
+            break;
+        }
+        case 0x00008000: {
+            switch (opc & 0x00000208) {
+                case 0x00000000: {
+                    *l = 16;
+                    *t = &avr_translate_LDDZ;
+                    break;
+                }
+                case 0x00000008: {
+                    *l = 16;
+                    *t = &avr_translate_LDDY;
+                    break;
+                }
+                case 0x00000200: {
+                    *l = 16;
+                    *t = &avr_translate_STDZ;
+                    break;
+                }
+                case 0x00000208: {
+                    *l = 16;
+                    *t = &avr_translate_STDY;
+                    break;
+                }
+            }
+            break;
+        }
+        case 0x00009000: {
+            switch (opc & 0x00002800) {
+                case 0x00000000: {
+                    switch (opc & 0x00000600) {
+                        case 0x00000000: {
+                            switch (opc & 0x0000000f) {
+                                case 0x00000000: {
+                                    *l = 32;
+                                    *t = &avr_translate_LDS;
+                                    break;
+                                }
+                                case 0x00000001: {
+                                    *l = 16;
+                                    *t = &avr_translate_LDZ2;
+                                    break;
+                                }
+                                case 0x00000002: {
+                                    *l = 16;
+                                    *t = &avr_translate_LDZ3;
+                                    break;
+                                }
+                                case 0x00000003: {
+                                    break;
+                                }
+                                case 0x00000004: {
+                                    *l = 16;
+                                    *t = &avr_translate_LPM2;
+                                    break;
+                                }
+                                case 0x00000005: {
+                                    *l = 16;
+                                    *t = &avr_translate_LPMX;
+                                    break;
+                                }
+                                case 0x00000006: {
+                                    *l = 16;
+                                    *t = &avr_translate_ELPM2;
+                                    break;
+                                }
+                                case 0x00000007: {
+                                    *l = 16;
+                                    *t = &avr_translate_ELPMX;
+                                    break;
+                                }
+                                case 0x00000008: {
+                                    break;
+                                }
+                                case 0x00000009: {
+                                    *l = 16;
+                                    *t = &avr_translate_LDY2;
+                                    break;
+                                }
+                                case 0x0000000a: {
+                                    *l = 16;
+                                    *t = &avr_translate_LDY3;
+                                    break;
+                                }
+                                case 0x0000000b: {
+                                    break;
+                                }
+                                case 0x0000000c: {
+                                    *l = 16;
+                                    *t = &avr_translate_LDX1;
+                                    break;
+                                }
+                                case 0x0000000d: {
+                                    *l = 16;
+                                    *t = &avr_translate_LDX2;
+                                    break;
+                                }
+                                case 0x0000000e: {
+                                    *l = 16;
+                                    *t = &avr_translate_LDX3;
+                                    break;
+                                }
+                                case 0x0000000f: {
+                                    *l = 16;
+                                    *t = &avr_translate_POP;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case 0x00000200: {
+                            switch (opc & 0x0000000f) {
+                                case 0x00000000: {
+                                    *l = 32;
+                                    *t = &avr_translate_STS;
+                                    break;
+                                }
+                                case 0x00000001: {
+                                    *l = 16;
+                                    *t = &avr_translate_STZ2;
+                                    break;
+                                }
+                                case 0x00000002: {
+                                    *l = 16;
+                                    *t = &avr_translate_STZ3;
+                                    break;
+                                }
+                                case 0x00000003: {
+                                    break;
+                                }
+                                case 0x00000004: {
+                                    *l = 16;
+                                    *t = &avr_translate_XCH;
+                                    break;
+                                }
+                                case 0x00000005: {
+                                    *l = 16;
+                                    *t = &avr_translate_LAS;
+                                    break;
+                                }
+                                case 0x00000006: {
+                                    *l = 16;
+                                    *t = &avr_translate_LAC;
+                                    break;
+                                }
+                                case 0x00000007: {
+                                    *l = 16;
+                                    *t = &avr_translate_LAT;
+                                    break;
+                                }
+                                case 0x00000008: {
+                                    break;
+                                }
+                                case 0x00000009: {
+                                    *l = 16;
+                                    *t = &avr_translate_STY2;
+                                    break;
+                                }
+                                case 0x0000000a: {
+                                    *l = 16;
+                                    *t = &avr_translate_STY3;
+                                    break;
+                                }
+                                case 0x0000000b: {
+                                    break;
+                                }
+                                case 0x0000000c: {
+                                    *l = 16;
+                                    *t = &avr_translate_STX1;
+                                    break;
+                                }
+                                case 0x0000000d: {
+                                    *l = 16;
+                                    *t = &avr_translate_STX2;
+                                    break;
+                                }
+                                case 0x0000000e: {
+                                    *l = 16;
+                                    *t = &avr_translate_STX3;
+                                    break;
+                                }
+                                case 0x0000000f: {
+                                    *l = 16;
+                                    *t = &avr_translate_PUSH;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case 0x00000400: {
+                            switch (opc & 0x0000000e) {
+                                case 0x00000000: {
+                                    switch (opc & 0x00000001) {
+                                        case 0x00000000: {
+                                            *l = 16;
+                                            *t = &avr_translate_COM;
+                                            break;
+                                        }
+                                        case 0x00000001: {
+                                            *l = 16;
+                                            *t = &avr_translate_NEG;
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case 0x00000002: {
+                                    switch (opc & 0x00000001) {
+                                        case 0x00000000: {
+                                            *l = 16;
+                                            *t = &avr_translate_SWAP;
+                                            break;
+                                        }
+                                        case 0x00000001: {
+                                            *l = 16;
+                                            *t = &avr_translate_INC;
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case 0x00000004: {
+                                    *l = 16;
+                                    *t = &avr_translate_ASR;
+                                    break;
+                                }
+                                case 0x00000006: {
+                                    switch (opc & 0x00000001) {
+                                        case 0x00000000: {
+                                            *l = 16;
+                                            *t = &avr_translate_LSR;
+                                            break;
+                                        }
+                                        case 0x00000001: {
+                                            *l = 16;
+                                            *t = &avr_translate_ROR;
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case 0x00000008: {
+                                    switch (opc & 0x00000181) {
+                                        case 0x00000000: {
+                                            *l = 16;
+                                            *t = &avr_translate_BSET;
+                                            break;
+                                        }
+                                        case 0x00000001: {
+                                            switch (opc & 0x00000010) {
+                                                case 0x00000000: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_IJMP;
+                                                    break;
+                                                }
+                                                case 0x00000010: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_EIJMP;
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        case 0x00000080: {
+                                            *l = 16;
+                                            *t = &avr_translate_BCLR;
+                                            break;
+                                        }
+                                        case 0x00000081: {
+                                            break;
+                                        }
+                                        case 0x00000100: {
+                                            switch (opc & 0x00000010) {
+                                                case 0x00000000: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_RET;
+                                                    break;
+                                                }
+                                                case 0x00000010: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_RETI;
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        case 0x00000101: {
+                                            switch (opc & 0x00000010) {
+                                                case 0x00000000: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_ICALL;
+                                                    break;
+                                                }
+                                                case 0x00000010: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_EICALL;
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        case 0x00000180: {
+                                            switch (opc & 0x00000070) {
+                                                case 0x00000000: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_SLEEP;
+                                                    break;
+                                                }
+                                                case 0x00000010: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_BREAK;
+                                                    break;
+                                                }
+                                                case 0x00000020: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_WDR;
+                                                    break;
+                                                }
+                                                case 0x00000030: {
+                                                    break;
+                                                }
+                                                case 0x00000040: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_LPM1;
+                                                    break;
+                                                }
+                                                case 0x00000050: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_ELPM1;
+                                                    break;
+                                                }
+                                                case 0x00000060: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_SPM;
+                                                    break;
+                                                }
+                                                case 0x00000070: {
+                                                    *l = 16;
+                                                    *t = &avr_translate_SPMX;
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        case 0x00000181: {
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case 0x0000000a: {
+                                    switch (opc & 0x00000001) {
+                                        case 0x00000000: {
+                                            *l = 16;
+                                            *t = &avr_translate_DEC;
+                                            break;
+                                        }
+                                        case 0x00000001: {
+                                            *l = 16;
+                                            *t = &avr_translate_DES;
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case 0x0000000c: {
+                                    *l = 32;
+                                    *t = &avr_translate_JMP;
+                                    break;
+                                }
+                                case 0x0000000e: {
+                                    *l = 32;
+                                    *t = &avr_translate_CALL;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case 0x00000600: {
+                            switch (opc & 0x00000100) {
+                                case 0x00000000: {
+                                    *l = 16;
+                                    *t = &avr_translate_ADIW;
+                                    break;
+                                }
+                                case 0x00000100: {
+                                    *l = 16;
+                                    *t = &avr_translate_SBIW;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case 0x00000800: {
+                    switch (opc & 0x00000400) {
+                        case 0x00000000: {
+                            switch (opc & 0x00000300) {
+                                case 0x00000000: {
+                                    *l = 16;
+                                    *t = &avr_translate_CBI;
+                                    break;
+                                }
+                                case 0x00000100: {
+                                    *l = 16;
+                                    *t = &avr_translate_SBIC;
+                                    break;
+                                }
+                                case 0x00000200: {
+                                    *l = 16;
+                                    *t = &avr_translate_SBI;
+                                    break;
+                                }
+                                case 0x00000300: {
+                                    *l = 16;
+                                    *t = &avr_translate_SBIS;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case 0x00000400: {
+                            *l = 16;
+                            *t = &avr_translate_MUL;
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case 0x00002000: {
+                    *l = 16;
+                    *t = &avr_translate_IN;
+                    break;
+                }
+                case 0x00002800: {
+                    *l = 16;
+                    *t = &avr_translate_OUT;
+                    break;
+                }
+            }
+            break;
+        }
+        case 0x0000c000: {
+            switch (opc & 0x00002000) {
+                case 0x00000000: {
+                    *l = 16;
+                    *t = &avr_translate_RJMP;
+                    break;
+                }
+                case 0x00002000: {
+                    *l = 16;
+                    *t = &avr_translate_LDI;
+                    break;
+                }
+            }
+            break;
+        }
+        case 0x0000d000: {
+            switch (opc & 0x00002000) {
+                case 0x00000000: {
+                    *l = 16;
+                    *t = &avr_translate_RCALL;
+                    break;
+                }
+                case 0x00002000: {
+                    switch (opc & 0x00000c00) {
+                        case 0x00000000: {
+                            *l = 16;
+                            *t = &avr_translate_BRBS;
+                            break;
+                        }
+                        case 0x00000400: {
+                            *l = 16;
+                            *t = &avr_translate_BRBC;
+                            break;
+                        }
+                        case 0x00000800: {
+                            switch (opc & 0x00000200) {
+                                case 0x00000000: {
+                                    *l = 16;
+                                    *t = &avr_translate_BLD;
+                                    break;
+                                }
+                                case 0x00000200: {
+                                    *l = 16;
+                                    *t = &avr_translate_BST;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case 0x00000c00: {
+                            switch (opc & 0x00000200) {
+                                case 0x00000000: {
+                                    *l = 16;
+                                    *t = &avr_translate_SBRC;
+                                    break;
+                                }
+                                case 0x00000200: {
+                                    *l = 16;
+                                    *t = &avr_translate_SBRS;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    break;
+                }
+            }
+            break;
+        }
+    }
+}
diff --git a/target-avr/translate.c b/target-avr/translate.c
index ec79ab0..c7fbf66 100644
--- a/target-avr/translate.c
+++ b/target-avr/translate.c
@@ -90,6 +90,8 @@ static void decode_opc(AVRCPU *cpu, DisasContext *ctx, InstInfo *inst)
     inst->length = 16;
     inst->translate = NULL;
 
+    avr_decode(inst->cpc, &inst->length, inst->opcode, &inst->translate);
+
     if (inst->length == 16) {
         inst->npc = inst->cpc + 1;
         /* get opcode as 16bit value */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 10/13] target-avr: Put env pointer in DisasContext
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (8 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 09/13] target-avr: adding instruction decoder Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 11/13] target-avr: Put all translation code into one compilation unit Richard Henderson
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/translate-inst.c | 298 ++++++++++++++++++++++----------------------
 target-avr/translate-inst.h | 194 ++++++++++++++--------------
 target-avr/translate.c      |  16 +--
 target-avr/translate.h      |  11 +-
 4 files changed, 257 insertions(+), 262 deletions(-)

diff --git a/target-avr/translate-inst.c b/target-avr/translate-inst.c
index 6ed98bb..377263a 100644
--- a/target-avr/translate-inst.c
+++ b/target-avr/translate-inst.c
@@ -109,9 +109,9 @@ static void gen_ZNSf(TCGv R)
     tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
 }
 
-static void gen_push_ret(CPUAVRState *env, int ret)
+static void gen_push_ret(DisasContext *ctx, int ret)
 {
-    if (avr_feature(env, AVR_FEATURE_1_BYTE_PC)) {
+    if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
 
         TCGv t0 = tcg_const_i32((ret & 0x0000ff));
 
@@ -119,7 +119,7 @@ static void gen_push_ret(CPUAVRState *env, int ret)
         tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
 
         tcg_temp_free_i32(t0);
-    } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) {
+    } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
 
         TCGv t0 = tcg_const_i32((ret & 0x00ffff));
 
@@ -129,7 +129,7 @@ static void gen_push_ret(CPUAVRState *env, int ret)
 
         tcg_temp_free_i32(t0);
 
-    } else if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+    } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
 
         TCGv lo = tcg_const_i32((ret & 0x0000ff));
         TCGv hi = tcg_const_i32((ret & 0xffff00) >> 8);
@@ -144,20 +144,20 @@ static void gen_push_ret(CPUAVRState *env, int ret)
     }
 }
 
-static void gen_pop_ret(CPUAVRState *env, TCGv ret)
+static void gen_pop_ret(DisasContext *ctx, TCGv ret)
 {
-    if (avr_feature(env, AVR_FEATURE_1_BYTE_PC)) {
+    if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
 
         tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
         tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_UB);
 
-    } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) {
+    } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
 
         tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
         tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_BEUW);
         tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
 
-    } else if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+    } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
 
         TCGv lo = tcg_temp_new_i32();
         TCGv hi = tcg_temp_new_i32();
@@ -249,7 +249,7 @@ static TCGv gen_get_zaddr(void)
  *  Adds two registers and the contents of the C Flag and places the result in
  *  the destination register Rd.
  */
-int avr_translate_ADC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ADC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[ADC_Rd(opcode)];
     TCGv Rr = cpu_r[ADC_Rr(opcode)];
@@ -276,7 +276,7 @@ int avr_translate_ADC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Adds two registers without the C Flag and places the result in the
  *  destination register Rd.
  */
-int avr_translate_ADD(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ADD(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[ADD_Rd(opcode)];
     TCGv Rr = cpu_r[ADD_Rr(opcode)];
@@ -305,9 +305,9 @@ int avr_translate_ADD(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  instruction is not available in all devices. Refer to the device specific
  *  instruction set summary.
  */
-int avr_translate_ADIW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ADIW(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_ADIW_SBIW) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -355,7 +355,7 @@ int avr_translate_ADIW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Performs the logical AND between the contents of register Rd and register
  *  Rr and places the result in the destination register Rd.
  */
-int avr_translate_AND(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_AND(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[AND_Rd(opcode)];
     TCGv Rr = cpu_r[AND_Rr(opcode)];
@@ -384,7 +384,7 @@ int avr_translate_AND(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Performs the logical AND between the contents of register Rd and a constant
  *  and places the result in the destination register Rd.
  */
-int avr_translate_ANDI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ANDI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + ANDI_Rd(opcode)];
     int Imm = (ANDI_Imm(opcode));
@@ -404,7 +404,7 @@ int avr_translate_ANDI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  signed value by two without changing its sign. The Carry Flag can be used to
  *  round the result.
  */
-int avr_translate_ASR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ASR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[ASR_Rd(opcode)];
     TCGv t1 = tcg_temp_new_i32();
@@ -435,7 +435,7 @@ int avr_translate_ASR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  Clears a single Flag in SREG.
  */
-int avr_translate_BCLR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_BCLR(DisasContext *ctx, uint32_t opcode)
 {
     switch (BCLR_Bit(opcode)) {
     case 0x00:
@@ -470,7 +470,7 @@ int avr_translate_BCLR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  Copies the T Flag in the SREG (Status Register) to bit b in register Rd.
  */
-int avr_translate_BLD(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_BLD(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[BLD_Rd(opcode)];
     TCGv t1 = tcg_temp_new_i32();
@@ -491,7 +491,7 @@ int avr_translate_BLD(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  parameter k is the offset from PC and is represented in two's complement
  *  form.
  */
-int avr_translate_BRBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_BRBC(DisasContext *ctx, uint32_t opcode)
 {
     TCGLabel *taken = gen_new_label();
     int Imm = sextract32(BRBC_Imm(opcode), 0, 7);
@@ -523,9 +523,9 @@ int avr_translate_BRBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
         break;
     }
 
-    gen_goto_tb(env, ctx, 1, ctx->inst[0].npc);
+    gen_goto_tb(ctx, 1, ctx->inst[0].npc);
     gen_set_label(taken);
-    gen_goto_tb(env, ctx, 0, ctx->inst[0].npc + Imm);
+    gen_goto_tb(ctx, 0, ctx->inst[0].npc + Imm);
 
     return BS_BRANCH;
 }
@@ -536,7 +536,7 @@ int avr_translate_BRBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  PC in either direction (PC - 63 < = destination <= PC + 64). The parameter k
  *  is the offset from PC and is represented in two's complement form.
  */
-int avr_translate_BRBS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_BRBS(DisasContext *ctx, uint32_t opcode)
 {
     TCGLabel *taken = gen_new_label();
     int Imm = sextract32(BRBS_Imm(opcode), 0, 7);
@@ -568,9 +568,9 @@ int avr_translate_BRBS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
         break;
     }
 
-    gen_goto_tb(env, ctx, 1, ctx->inst[0].npc);
+    gen_goto_tb(ctx, 1, ctx->inst[0].npc);
     gen_set_label(taken);
-    gen_goto_tb(env, ctx, 0, ctx->inst[0].npc + Imm);
+    gen_goto_tb(ctx, 0, ctx->inst[0].npc + Imm);
 
     return BS_BRANCH;
 }
@@ -578,7 +578,7 @@ int avr_translate_BRBS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  Sets a single Flag or bit in SREG.
  */
-int avr_translate_BSET(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_BSET(DisasContext *ctx, uint32_t opcode)
 {
     switch (BSET_Bit(opcode)) {
     case 0x00:
@@ -620,9 +620,9 @@ int avr_translate_BSET(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  is not available in all devices. Refer to the device specific instruction
  *  set summary.
  */
-int avr_translate_BREAK(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_BREAK(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_BREAK) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_BREAK) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -635,7 +635,7 @@ int avr_translate_BREAK(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  Stores bit b from Rd to the T Flag in SREG (Status Register).
  */
-int avr_translate_BST(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_BST(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[BST_Rd(opcode)];
 
@@ -652,9 +652,9 @@ int avr_translate_BST(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  CALL.  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_CALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_CALL(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_JMP_CALL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_JMP_CALL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -663,9 +663,8 @@ int avr_translate_CALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     int Imm = CALL_Imm(opcode);
     int ret = ctx->inst[0].npc;
 
-    gen_push_ret(env, ret);
-
-    gen_goto_tb(env, ctx, 0, Imm);
+    gen_push_ret(ctx, ret);
+    gen_goto_tb(ctx, 0, Imm);
 
     return BS_BRANCH;
 }
@@ -674,7 +673,7 @@ int avr_translate_CALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Clears a specified bit in an I/O Register. This instruction operates on
  *  the lower 32 I/O Registers -- addresses 0-31.
  */
-int avr_translate_CBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_CBI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv data = tcg_temp_new_i32();
     TCGv port = tcg_const_i32(CBI_Imm(opcode));
@@ -694,7 +693,7 @@ int avr_translate_CBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  between the contents of register Rd and the complement of the constant mask
  *  K. The result will be placed in register Rd.
  */
-int avr_translate_COM(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_COM(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[COM_Rd(opcode)];
     TCGv R = tcg_temp_new_i32();
@@ -715,7 +714,7 @@ int avr_translate_COM(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  None of the registers are changed. All conditional branches can be used
  *  after this instruction.
  */
-int avr_translate_CP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_CP(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[CP_Rd(opcode)];
     TCGv Rr = cpu_r[CP_Rr(opcode)];
@@ -739,7 +738,7 @@ int avr_translate_CP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  also takes into account the previous carry. None of the registers are
  *  changed. All conditional branches can be used after this instruction.
  */
-int avr_translate_CPC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_CPC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[CPC_Rd(opcode)];
     TCGv Rr = cpu_r[CPC_Rr(opcode)];
@@ -769,7 +768,7 @@ int avr_translate_CPC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  The register is not changed. All conditional branches can be used after this
  *  instruction.
  */
-int avr_translate_CPI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_CPI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + CPI_Rd(opcode)];
     int Imm = CPI_Imm(opcode);
@@ -794,7 +793,7 @@ int avr_translate_CPI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction performs a compare between two registers Rd and Rr, and
  *  skips the next instruction if Rd = Rr.
  */
-int avr_translate_CPSE(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_CPSE(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[CPSE_Rd(opcode)];
     TCGv Rr = cpu_r[CPSE_Rr(opcode)];
@@ -818,7 +817,7 @@ int avr_translate_CPSE(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  BREQ and BRNE branches can be expected to perform consistently.  When
  *  operating on two's complement values, all signed branches are available.
  */
-int avr_translate_DEC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_DEC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[DEC_Rd(opcode)];
 
@@ -852,10 +851,10 @@ int avr_translate_DEC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  affect the result in the final ciphertext or plaintext, but reduces
  *  execution time.
  */
-int avr_translate_DES(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_DES(DisasContext *ctx, uint32_t opcode)
 {
     /* TODO: */
-    if (avr_feature(env, AVR_FEATURE_DES) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_DES) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -872,9 +871,9 @@ int avr_translate_DES(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  during EICALL.  This instruction is not available in all devices. Refer to
  *  the device specific instruction set summary.
  */
-int avr_translate_EICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_EICALL(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_EIJMP_EICALL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_EIJMP_EICALL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -882,7 +881,7 @@ int avr_translate_EICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 
     int ret = ctx->inst[0].npc;
 
-    gen_push_ret(env, ret);
+    gen_push_ret(ctx, ret);
 
     gen_jmp_ez();
 
@@ -896,9 +895,9 @@ int avr_translate_EICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  memory space. See also IJMP.  This instruction is not available in all
  *  devices. Refer to the device specific instruction set summary.
  */
-int avr_translate_EIJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_EIJMP(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_EIJMP_EICALL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_EIJMP_EICALL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -925,9 +924,9 @@ int avr_translate_EIJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  instruction is not available in all devices. Refer to the device specific
  *  instruction set summary.
  */
-int avr_translate_ELPM1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ELPM1(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_ELPM) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_ELPM) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -943,9 +942,9 @@ int avr_translate_ELPM1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_ELPM2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ELPM2(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_ELPM) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_ELPM) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -961,9 +960,9 @@ int avr_translate_ELPM2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_ELPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ELPMX(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_ELPMX) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_ELPMX) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -987,7 +986,7 @@ int avr_translate_ELPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Performs the logical EOR between the contents of register Rd and
  *  register Rr and places the result in the destination register Rd.
  */
-int avr_translate_EOR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_EOR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[EOR_Rd(opcode)];
     TCGv Rr = cpu_r[EOR_Rr(opcode)];
@@ -1004,9 +1003,9 @@ int avr_translate_EOR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned
  *  multiplication and shifts the result one bit left.
  */
-int avr_translate_FMUL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_FMUL(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1037,9 +1036,9 @@ int avr_translate_FMUL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
  *  and shifts the result one bit left.
  */
-int avr_translate_FMULS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_FMULS(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1076,9 +1075,9 @@ int avr_translate_FMULS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
  *  and shifts the result one bit left.
  */
-int avr_translate_FMULSU(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_FMULSU(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1115,9 +1114,9 @@ int avr_translate_FMULSU(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  CALL.  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_ICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ICALL(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_IJMP_ICALL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_IJMP_ICALL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1125,7 +1124,7 @@ int avr_translate_ICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 
     int ret = ctx->inst[0].npc;
 
-    gen_push_ret(env, ret);
+    gen_push_ret(ctx, ret);
     gen_jmp_z();
 
     return BS_BRANCH;
@@ -1138,9 +1137,9 @@ int avr_translate_ICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_IJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_IJMP(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_IJMP_ICALL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_IJMP_ICALL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1155,7 +1154,7 @@ int avr_translate_IJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Loads data from the I/O Space (Ports, Timers, Configuration Registers,
  *  etc.) into register Rd in the Register File.
  */
-int avr_translate_IN(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_IN(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[IN_Rd(opcode)];
     int Imm = IN_Imm(opcode);
@@ -1176,7 +1175,7 @@ int avr_translate_IN(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  BREQ and BRNE branches can be expected to perform consistently. When
  *  operating on two's complement values, all signed branches are available.
  */
-int avr_translate_INC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_INC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[INC_Rd(opcode)];
 
@@ -1194,15 +1193,15 @@ int avr_translate_INC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  RJMP.  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.0
  */
-int avr_translate_JMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_JMP(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_JMP_CALL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_JMP_CALL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
     }
 
-    gen_goto_tb(env, ctx, 0, JMP_Imm(opcode));
+    gen_goto_tb(ctx, 0, JMP_Imm(opcode));
     return BS_BRANCH;
 }
 
@@ -1234,9 +1233,9 @@ static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr)
     }
 }
 
-int avr_translate_LAC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LAC(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1271,9 +1270,9 @@ int avr_translate_LAC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  The Z-pointer Register is left unchanged by the operation. This instruction
  *  is especially suited for setting status bits stored in SRAM.
  */
-int avr_translate_LAS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LAS(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1307,9 +1306,9 @@ int avr_translate_LAS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  The Z-pointer Register is left unchanged by the operation. This instruction
  *  is especially suited for changing status bits stored in SRAM.
  */
-int avr_translate_LAT(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LAT(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1358,7 +1357,7 @@ int avr_translate_LAT(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  operation as LPM since the program memory is mapped to the data memory
  *  space.
  */
-int avr_translate_LDX1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDX1(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDX1_Rd(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -1370,7 +1369,7 @@ int avr_translate_LDX1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDX2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDX2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDX2_Rd(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -1385,7 +1384,7 @@ int avr_translate_LDX2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDX3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDX3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDX3_Rd(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -1424,7 +1423,7 @@ int avr_translate_LDX3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  be used to achieve the same operation as LPM since the program memory is
  *  mapped to the data memory space.
  */
-int avr_translate_LDY2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDY2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDY2_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -1439,7 +1438,7 @@ int avr_translate_LDY2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDY3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDY3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDY3_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -1453,7 +1452,7 @@ int avr_translate_LDY3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDDY(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDDY(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDDY_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -1495,7 +1494,7 @@ int avr_translate_LDDY(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  space.  For using the Z-pointer for table lookup in Program memory see the
  *  LPM and ELPM instructions.
  */
-int avr_translate_LDZ2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDZ2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDZ2_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -1510,7 +1509,7 @@ int avr_translate_LDZ2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDZ3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDZ3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDZ3_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -1525,7 +1524,7 @@ int avr_translate_LDZ3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDDZ(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDDZ(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDDZ_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -1542,7 +1541,7 @@ int avr_translate_LDDZ(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
     Loads an 8 bit constant directly to register 16 to 31.
  */
-int avr_translate_LDI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + LDI_Rd(opcode)];
     int imm = LDI_Imm(opcode);
@@ -1564,7 +1563,7 @@ int avr_translate_LDI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_LDS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LDS(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDS_Rd(opcode)];
     TCGv addr = tcg_temp_new_i32();
@@ -1596,9 +1595,9 @@ int avr_translate_LDS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  available in all devices. Refer to the device specific instruction set
  *  summary
  */
-int avr_translate_LPM1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LPM1(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_LPM) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_LPM) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1619,9 +1618,9 @@ int avr_translate_LPM1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LPM2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LPM2(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_LPM) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_LPM) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1642,9 +1641,9 @@ int avr_translate_LPM2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LPMX(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_LPMX) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_LPMX) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1677,7 +1676,7 @@ int avr_translate_LPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  loaded into the C Flag of the SREG. This operation effectively divides an
  *  unsigned value by two. The C Flag can be used to round the result.
  */
-int avr_translate_LSR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_LSR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LSR_Rd(opcode)];
 
@@ -1695,7 +1694,7 @@ int avr_translate_LSR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  register Rr is left unchanged, while the destination register Rd is loaded
  *  with a copy of Rr.
  */
-int avr_translate_MOV(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_MOV(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[MOV_Rd(opcode)];
     TCGv Rr = cpu_r[MOV_Rr(opcode)];
@@ -1712,9 +1711,9 @@ int avr_translate_MOV(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  instruction is not available in all devices. Refer to the device specific
  *  instruction set summary.
  */
-int avr_translate_MOVW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_MOVW(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_MOVW) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_MOVW) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1734,9 +1733,9 @@ int avr_translate_MOVW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication.
  */
-int avr_translate_MUL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_MUL(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1766,9 +1765,9 @@ int avr_translate_MUL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication.
  */
-int avr_translate_MULS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_MULS(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1806,9 +1805,9 @@ int avr_translate_MULS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a
  *  signed and an unsigned number.
  */
-int avr_translate_MULSU(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_MULSU(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_MUL) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -1843,7 +1842,7 @@ int avr_translate_MULSU(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Replaces the contents of register Rd with its two's complement; the
  *  value $80 is left unchanged.
  */
-int avr_translate_NEG(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_NEG(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[SUB_Rd(opcode)];
     TCGv t0 = tcg_const_i32(0);
@@ -1869,7 +1868,7 @@ int avr_translate_NEG(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  This instruction performs a single cycle No Operation.
  */
-int avr_translate_NOP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_NOP(DisasContext *ctx, uint32_t opcode)
 {
 
     /* NOP */
@@ -1881,7 +1880,7 @@ int avr_translate_NOP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Performs the logical OR between the contents of register Rd and register
  *  Rr and places the result in the destination register Rd.
  */
-int avr_translate_OR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_OR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[OR_Rd(opcode)];
     TCGv Rr = cpu_r[OR_Rr(opcode)];
@@ -1901,7 +1900,7 @@ int avr_translate_OR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Performs the logical OR between the contents of register Rd and a
  *  constant and places the result in the destination register Rd.
  */
-int avr_translate_ORI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ORI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + ORI_Rd(opcode)];
     int Imm = (ORI_Imm(opcode));
@@ -1918,7 +1917,7 @@ int avr_translate_ORI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Stores data from register Rr in the Register File to I/O Space (Ports,
  *  Timers, Configuration Registers, etc.).
  */
-int avr_translate_OUT(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_OUT(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[OUT_Rd(opcode)];
     int Imm = OUT_Imm(opcode);
@@ -1937,7 +1936,7 @@ int avr_translate_OUT(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  available in all devices. Refer to the device specific instruction set
  *  summary.
  */
-int avr_translate_POP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_POP(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[POP_Rd(opcode)];
 
@@ -1953,7 +1952,7 @@ int avr_translate_POP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  not available in all devices. Refer to the device specific instruction set
  *  summary.
  */
-int avr_translate_PUSH(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_PUSH(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[PUSH_Rd(opcode)];
 
@@ -1971,14 +1970,13 @@ int avr_translate_PUSH(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  address location. The Stack Pointer uses a post-decrement scheme during
  *  RCALL.
  */
-int avr_translate_RCALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_RCALL(DisasContext *ctx, uint32_t opcode)
 {
     int ret = ctx->inst[0].npc;
     int dst = ctx->inst[0].npc + sextract32(RCALL_Imm(opcode), 0, 12);
 
-    gen_push_ret(env, ret);
-
-    gen_goto_tb(env, ctx, 0, dst);
+    gen_push_ret(ctx, ret);
+    gen_goto_tb(ctx, 0, dst);
 
     return BS_BRANCH;
 }
@@ -1987,9 +1985,9 @@ int avr_translate_RCALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Returns from subroutine. The return address is loaded from the STACK.
  *  The Stack Pointer uses a preincrement scheme during RET.
  */
-int avr_translate_RET(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_RET(DisasContext *ctx, uint32_t opcode)
 {
-    gen_pop_ret(env, cpu_pc);
+    gen_pop_ret(ctx, cpu_pc);
 
     tcg_gen_exit_tb(0);
 
@@ -2004,9 +2002,9 @@ int avr_translate_RET(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  the application program. The Stack Pointer uses a pre-increment scheme
  *  during RETI.
  */
-int avr_translate_RETI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_RETI(DisasContext *ctx, uint32_t opcode)
 {
-    gen_pop_ret(env, cpu_pc);
+    gen_pop_ret(ctx, cpu_pc);
 
     tcg_gen_movi_tl(cpu_If, 1);
 
@@ -2021,11 +2019,11 @@ int avr_translate_RETI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  instruction can address the entire memory from every address location. See
  *  also JMP.
  */
-int avr_translate_RJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_RJMP(DisasContext *ctx, uint32_t opcode)
 {
     int dst = ctx->inst[0].npc + sextract32(RJMP_Imm(opcode), 0, 12);
 
-    gen_goto_tb(env, ctx, 0, dst);
+    gen_goto_tb(ctx, 0, dst);
 
     return BS_BRANCH;
 }
@@ -2037,7 +2035,7 @@ int avr_translate_RJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  LSR it effectively divides multi-byte unsigned values by two. The Carry Flag
  *  can be used to round the result.
  */
-int avr_translate_ROR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_ROR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[ROR_Rd(opcode)];
     TCGv t0 = tcg_temp_new_i32();
@@ -2059,7 +2057,7 @@ int avr_translate_ROR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Subtracts two registers and subtracts with the C Flag and places the
  *  result in the destination register Rd.
  */
-int avr_translate_SBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SBC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[SBC_Rd(opcode)];
     TCGv Rr = cpu_r[SBC_Rr(opcode)];
@@ -2085,7 +2083,7 @@ int avr_translate_SBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  SBCI -- Subtract Immediate with Carry
  */
-int avr_translate_SBCI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SBCI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + SBCI_Rd(opcode)];
     TCGv Rr = tcg_const_i32(SBCI_Imm(opcode));
@@ -2113,7 +2111,7 @@ int avr_translate_SBCI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Sets a specified bit in an I/O Register. This instruction operates on
  *  the lower 32 I/O Registers -- addresses 0-31.
  */
-int avr_translate_SBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SBI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv data = tcg_temp_new_i32();
     TCGv port = tcg_const_i32(SBI_Imm(opcode));
@@ -2133,7 +2131,7 @@ int avr_translate_SBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  next instruction if the bit is cleared. This instruction operates on the
  *  lower 32 I/O Registers -- addresses 0-31.
  */
-int avr_translate_SBIC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SBIC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv data = tcg_temp_new_i32();
     TCGv port = tcg_const_i32(SBIC_Imm(opcode));
@@ -2160,7 +2158,7 @@ int avr_translate_SBIC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  next instruction if the bit is set. This instruction operates on the lower
  *  32 I/O Registers -- addresses 0-31.
  */
-int avr_translate_SBIS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SBIS(DisasContext *ctx, uint32_t opcode)
 {
     TCGv data = tcg_temp_new_i32();
     TCGv port = tcg_const_i32(SBIS_Imm(opcode));
@@ -2189,9 +2187,9 @@ int avr_translate_SBIS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_SBIW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SBIW(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_ADIW_SBIW) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -2239,7 +2237,7 @@ int avr_translate_SBIW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction tests a single bit in a register and skips the next
  *  instruction if the bit is cleared.
  */
-int avr_translate_SBRC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SBRC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rr = cpu_r[SBRC_Rr(opcode)];
     TCGv t0 = tcg_temp_new_i32();
@@ -2262,7 +2260,7 @@ int avr_translate_SBRC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction tests a single bit in a register and skips the next
  *  instruction if the bit is set.
  */
-int avr_translate_SBRS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SBRS(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rr = cpu_r[SBRS_Rr(opcode)];
     TCGv t0 = tcg_temp_new_i32();
@@ -2285,7 +2283,7 @@ int avr_translate_SBRS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction sets the circuit in sleep mode defined by the MCU
  *  Control Register.
  */
-int avr_translate_SLEEP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SLEEP(DisasContext *ctx, uint32_t opcode)
 {
     gen_helper_sleep(cpu_env);
 
@@ -2309,9 +2307,9 @@ int avr_translate_SLEEP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  determines the instruction high byte, and R0 determines the instruction low
  *  byte.
  */
-int avr_translate_SPM(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SPM(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_SPM) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_SPM) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -2321,9 +2319,9 @@ int avr_translate_SPM(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_SPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SPMX(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_SPMX) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_SPMX) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
@@ -2333,7 +2331,7 @@ int avr_translate_SPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STX1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STX1(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STX1_Rr(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -2345,7 +2343,7 @@ int avr_translate_STX1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STX2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STX2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STX2_Rr(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -2359,7 +2357,7 @@ int avr_translate_STX2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STX3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STX3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STX3_Rr(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -2373,7 +2371,7 @@ int avr_translate_STX3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STY2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STY2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STY2_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -2387,7 +2385,7 @@ int avr_translate_STY2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STY3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STY3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STY3_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -2401,7 +2399,7 @@ int avr_translate_STY3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STDY(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STDY(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STDY_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -2415,7 +2413,7 @@ int avr_translate_STDY(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STZ2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STZ2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STZ2_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -2430,7 +2428,7 @@ int avr_translate_STZ2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STZ3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STZ3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STZ3_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -2445,7 +2443,7 @@ int avr_translate_STZ3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STDZ(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STDZ(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STDZ_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -2471,7 +2469,7 @@ int avr_translate_STDZ(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_STS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_STS(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STS_Rd(opcode)];
     TCGv addr = tcg_temp_new_i32();
@@ -2492,7 +2490,7 @@ int avr_translate_STS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  Subtracts two registers and places the result in the destination
  *  register Rd.
  */
-int avr_translate_SUB(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SUB(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[SUB_Rd(opcode)];
     TCGv Rr = cpu_r[SUB_Rr(opcode)];
@@ -2519,7 +2517,7 @@ int avr_translate_SUB(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  destination register Rd. This instruction is working on Register R16 to R31
  *  and is very well suited for operations on the X, Y, and Z-pointers.
  */
-int avr_translate_SUBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SUBI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + SUBI_Rd(opcode)];
     TCGv Rr = tcg_const_i32(SUBI_Imm(opcode));
@@ -2546,7 +2544,7 @@ int avr_translate_SUBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
 /*
  *  Swaps high and low nibbles in a register.
  */
-int avr_translate_SWAP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_SWAP(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[SWAP_Rd(opcode)];
     TCGv t0 = tcg_temp_new_i32();
@@ -2569,7 +2567,7 @@ int avr_translate_SWAP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  executed within a limited time given by the WD prescaler. See the Watchdog
  *  Timer hardware specification.
  */
-int avr_translate_WDR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_WDR(DisasContext *ctx, uint32_t opcode)
 {
     gen_helper_wdr(cpu_env);
 
@@ -2585,9 +2583,9 @@ int avr_translate_WDR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
  *  is left unchanged by the operation. This instruction is especially suited
  *  for writing/reading status bits stored in SRAM.
  */
-int avr_translate_XCH(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
+int avr_translate_XCH(DisasContext *ctx, uint32_t opcode)
 {
-    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
         gen_helper_unsupported(cpu_env);
 
         return BS_EXCP;
diff --git a/target-avr/translate-inst.h b/target-avr/translate-inst.h
index af2e076..47b0a3e 100644
--- a/target-avr/translate-inst.h
+++ b/target-avr/translate-inst.h
@@ -23,9 +23,9 @@
 
 typedef struct DisasContext DisasContext;
 
-int avr_translate_NOP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_NOP(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_MOVW(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_MOVW(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MOVW_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 4);
@@ -36,7 +36,7 @@ static inline uint32_t MOVW_Rd(uint32_t opcode)
     return extract32(opcode, 4, 4);
 }
 
-int avr_translate_MULS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_MULS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MULS_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 4);
@@ -47,7 +47,7 @@ static inline uint32_t MULS_Rd(uint32_t opcode)
     return extract32(opcode, 4, 4);
 }
 
-int avr_translate_MULSU(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_MULSU(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MULSU_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -58,7 +58,7 @@ static inline uint32_t MULSU_Rd(uint32_t opcode)
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_FMUL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_FMUL(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t FMUL_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -69,7 +69,7 @@ static inline uint32_t FMUL_Rd(uint32_t opcode)
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_FMULS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_FMULS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t FMULS_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -80,7 +80,7 @@ static inline uint32_t FMULS_Rd(uint32_t opcode)
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_FMULSU(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_FMULSU(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t FMULSU_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -91,7 +91,7 @@ static inline uint32_t FMULSU_Rd(uint32_t opcode)
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_CPC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_CPC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CPC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -103,7 +103,7 @@ static inline uint32_t CPC_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SBC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SBC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -115,7 +115,7 @@ static inline uint32_t SBC_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_ADD(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ADD(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ADD_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -127,7 +127,7 @@ static inline uint32_t ADD_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_AND(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_AND(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t AND_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -139,7 +139,7 @@ static inline uint32_t AND_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_EOR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_EOR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t EOR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -151,7 +151,7 @@ static inline uint32_t EOR_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_OR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_OR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t OR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -163,7 +163,7 @@ static inline uint32_t OR_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_MOV(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_MOV(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MOV_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -175,7 +175,7 @@ static inline uint32_t MOV_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_CPSE(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_CPSE(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CPSE_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -187,7 +187,7 @@ static inline uint32_t CPSE_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_CP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_CP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CP_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -199,7 +199,7 @@ static inline uint32_t CP_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SUB(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SUB(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SUB_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -211,7 +211,7 @@ static inline uint32_t SUB_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_ADC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ADC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ADC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -223,7 +223,7 @@ static inline uint32_t ADC_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_CPI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_CPI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CPI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -235,7 +235,7 @@ static inline uint32_t CPI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SBCI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SBCI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBCI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -247,7 +247,7 @@ static inline uint32_t SBCI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_ORI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ORI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ORI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -259,7 +259,7 @@ static inline uint32_t ORI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SUBI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SUBI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SUBI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -271,7 +271,7 @@ static inline uint32_t SUBI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_ANDI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ANDI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ANDI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -283,7 +283,7 @@ static inline uint32_t ANDI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_LDDZ(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDDZ(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDDZ_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -296,7 +296,7 @@ static inline uint32_t LDDZ_Imm(uint32_t opcode)
             (extract32(opcode, 0, 3));
 }
 
-int avr_translate_LDDY(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDDY(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDDY_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -309,7 +309,7 @@ static inline uint32_t LDDY_Imm(uint32_t opcode)
             (extract32(opcode, 0, 3));
 }
 
-int avr_translate_STDZ(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STDZ(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STDZ_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -322,7 +322,7 @@ static inline uint32_t STDZ_Imm(uint32_t opcode)
             (extract32(opcode, 0, 3));
 }
 
-int avr_translate_STDY(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STDY(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STDY_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -335,7 +335,7 @@ static inline uint32_t STDY_Imm(uint32_t opcode)
             (extract32(opcode, 0, 3));
 }
 
-int avr_translate_LDS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDS_Imm(uint32_t opcode)
 {
     return extract32(opcode, 0, 16);
@@ -346,79 +346,79 @@ static inline uint32_t LDS_Rd(uint32_t opcode)
     return extract32(opcode, 20, 5);
 }
 
-int avr_translate_LDZ2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDZ2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDZ2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDZ3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDZ3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDZ3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LPM2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LPM2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LPM2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LPMX(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LPMX(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LPMX_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_ELPM2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ELPM2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ELPM2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_ELPMX(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ELPMX(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ELPMX_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDY2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDY2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDY2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDY3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDY3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDY3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDX1(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDX1(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDX1_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDX2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDX2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDX2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDX3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDX3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDX3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_POP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_POP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t POP_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STS_Imm(uint32_t opcode)
 {
     return extract32(opcode, 0, 16);
@@ -429,185 +429,185 @@ static inline uint32_t STS_Rd(uint32_t opcode)
     return extract32(opcode, 20, 5);
 }
 
-int avr_translate_STZ2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STZ2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STZ2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STZ3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STZ3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STZ3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_XCH(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_XCH(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t XCH_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LAS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LAS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LAS_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LAC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LAC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LAC_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LAT(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LAT(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LAT_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STY2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STY2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STY2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STY3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STY3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STY3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STX1(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STX1(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STX1_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STX2(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STX2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STX2_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STX3(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_STX3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STX3_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_PUSH(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_PUSH(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t PUSH_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_COM(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_COM(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t COM_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_NEG(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_NEG(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t NEG_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_SWAP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SWAP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SWAP_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_INC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_INC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t INC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_ASR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ASR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ASR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LSR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LSR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LSR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_ROR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ROR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ROR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_BSET(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_BSET(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BSET_Bit(uint32_t opcode)
 {
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_IJMP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_IJMP(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_EIJMP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_EIJMP(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_BCLR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_BCLR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BCLR_Bit(uint32_t opcode)
 {
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_RET(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_RET(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_RETI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_RETI(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_ICALL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ICALL(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_EICALL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_EICALL(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_SLEEP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SLEEP(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_BREAK(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_BREAK(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_WDR(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_WDR(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_LPM1(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LPM1(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_ELPM1(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ELPM1(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_SPM(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SPM(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_SPMX(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SPMX(DisasContext* ctx, uint32_t opcode);
 
-int avr_translate_DEC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_DEC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t DEC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_DES(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_DES(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t DES_Imm(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
 }
 
-int avr_translate_JMP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_JMP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t JMP_Imm(uint32_t opcode)
 {
     return (extract32(opcode, 20, 5) << 17) |
             (extract32(opcode, 0, 17));
 }
 
-int avr_translate_CALL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_CALL(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CALL_Imm(uint32_t opcode)
 {
     return (extract32(opcode, 20, 5) << 17) |
             (extract32(opcode, 0, 17));
 }
 
-int avr_translate_ADIW(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_ADIW(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ADIW_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 2);
@@ -619,7 +619,7 @@ static inline uint32_t ADIW_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SBIW(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SBIW(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBIW_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 2);
@@ -631,7 +631,7 @@ static inline uint32_t SBIW_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_CBI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_CBI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CBI_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -642,7 +642,7 @@ static inline uint32_t CBI_Imm(uint32_t opcode)
     return extract32(opcode, 3, 5);
 }
 
-int avr_translate_SBIC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SBIC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBIC_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -653,7 +653,7 @@ static inline uint32_t SBIC_Imm(uint32_t opcode)
     return extract32(opcode, 3, 5);
 }
 
-int avr_translate_SBI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SBI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBI_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -664,7 +664,7 @@ static inline uint32_t SBI_Imm(uint32_t opcode)
     return extract32(opcode, 3, 5);
 }
 
-int avr_translate_SBIS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SBIS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBIS_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -675,7 +675,7 @@ static inline uint32_t SBIS_Imm(uint32_t opcode)
     return extract32(opcode, 3, 5);
 }
 
-int avr_translate_MUL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_MUL(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MUL_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -687,7 +687,7 @@ static inline uint32_t MUL_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_IN(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_IN(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t IN_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -699,7 +699,7 @@ static inline uint32_t IN_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_OUT(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_OUT(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t OUT_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -711,13 +711,13 @@ static inline uint32_t OUT_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_RJMP(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_RJMP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t RJMP_Imm(uint32_t opcode)
 {
     return extract32(opcode, 0, 12);
 }
 
-int avr_translate_LDI(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_LDI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -729,13 +729,13 @@ static inline uint32_t LDI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_RCALL(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_RCALL(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t RCALL_Imm(uint32_t opcode)
 {
     return extract32(opcode, 0, 12);
 }
 
-int avr_translate_BRBS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_BRBS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BRBS_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -746,7 +746,7 @@ static inline uint32_t BRBS_Imm(uint32_t opcode)
     return extract32(opcode, 3, 7);
 }
 
-int avr_translate_BRBC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_BRBC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BRBC_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -757,7 +757,7 @@ static inline uint32_t BRBC_Imm(uint32_t opcode)
     return extract32(opcode, 3, 7);
 }
 
-int avr_translate_BLD(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_BLD(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BLD_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -768,7 +768,7 @@ static inline uint32_t BLD_Rd(uint32_t opcode)
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_BST(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_BST(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BST_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -779,7 +779,7 @@ static inline uint32_t BST_Rd(uint32_t opcode)
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_SBRC(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SBRC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBRC_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -790,7 +790,7 @@ static inline uint32_t SBRC_Rr(uint32_t opcode)
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_SBRS(CPUAVRState *env, DisasContext* ctx, uint32_t opcode);
+int avr_translate_SBRS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBRS_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
diff --git a/target-avr/translate.c b/target-avr/translate.c
index c7fbf66..51471fc 100644
--- a/target-avr/translate.c
+++ b/target-avr/translate.c
@@ -82,11 +82,10 @@ void avr_translate_init(void)
     done_init = 1;
 }
 
-static void decode_opc(AVRCPU *cpu, DisasContext *ctx, InstInfo *inst)
+static void decode_opc(DisasContext *ctx, InstInfo *inst)
 {
-    CPUAVRState *env = &cpu->env;
-
-    inst->opcode = cpu_ldl_code(env, inst->cpc * 2);/* pc points to words */
+    /* PC points to words.  */
+    inst->opcode = cpu_ldl_code(ctx->env, inst->cpc * 2);
     inst->length = 16;
     inst->translate = NULL;
 
@@ -118,6 +117,7 @@ void gen_intermediate_code(CPUAVRState *env, struct TranslationBlock *tb)
 
     pc_start = tb->pc / 2;
     ctx.tb = tb;
+    ctx.env = env;
     ctx.memidx = 0;
     ctx.bstate = BS_NONE;
     ctx.singlestep = cs->singlestep_enabled;
@@ -143,7 +143,7 @@ void gen_intermediate_code(CPUAVRState *env, struct TranslationBlock *tb)
 
     /* decode first instruction */
     ctx.inst[0].cpc = pc_start;
-    decode_opc(cpu, &ctx, &ctx.inst[0]);
+    decode_opc(&ctx, &ctx.inst[0]);
     do {
         /* set curr/next PCs */
         cpc = ctx.inst[0].cpc;
@@ -151,7 +151,7 @@ void gen_intermediate_code(CPUAVRState *env, struct TranslationBlock *tb)
 
         /* decode next instruction */
         ctx.inst[1].cpc = ctx.inst[0].npc;
-        decode_opc(cpu, &ctx, &ctx.inst[1]);
+        decode_opc(&ctx, &ctx.inst[1]);
 
         /* translate current instruction */
         tcg_gen_insn_start(cpc);
@@ -172,7 +172,7 @@ void gen_intermediate_code(CPUAVRState *env, struct TranslationBlock *tb)
         }
 
         if (ctx.inst[0].translate) {
-            ctx.bstate = ctx.inst[0].translate(env, &ctx, ctx.inst[0].opcode);
+            ctx.bstate = ctx.inst[0].translate(&ctx, ctx.inst[0].opcode);
         }
 
         if (num_insns >= max_insns) {
@@ -202,7 +202,7 @@ void gen_intermediate_code(CPUAVRState *env, struct TranslationBlock *tb)
         switch (ctx.bstate) {
         case BS_STOP:
         case BS_NONE:
-            gen_goto_tb(env, &ctx, 0, npc);
+            gen_goto_tb(&ctx, 0, npc);
             break;
         case BS_EXCP:
             tcg_gen_exit_tb(0);
diff --git a/target-avr/translate.h b/target-avr/translate.h
index 711886e..fabbe69 100644
--- a/target-avr/translate.h
+++ b/target-avr/translate.h
@@ -69,8 +69,7 @@ uint32_t get_opcode(uint8_t const *code, unsigned bitBase, unsigned bitSize);
 typedef struct DisasContext DisasContext;
 typedef struct InstInfo InstInfo;
 
-typedef int (*translate_function_t)(CPUAVRState *env, DisasContext *ctx,
-                                        uint32_t opcode);
+typedef int (*translate_function_t)(DisasContext *ctx, uint32_t opcode);
 struct InstInfo {
     target_long cpc;
     target_long npc;
@@ -82,6 +81,7 @@ struct InstInfo {
 /* This is the state at translation time. */
 struct DisasContext {
     struct TranslationBlock *tb;
+    CPUAVRState *env;
 
     InstInfo inst[2];/* two consecutive instructions */
 
@@ -94,12 +94,9 @@ struct DisasContext {
 void avr_decode(uint32_t pc, uint32_t *length, uint32_t opcode,
                         translate_function_t *translate);
 
-static inline void gen_goto_tb(CPUAVRState *env, DisasContext *ctx,
-                        int n, target_ulong dest)
+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 {
-    TranslationBlock *tb;
-
-    tb = ctx->tb;
+    TranslationBlock *tb = ctx->tb;
 
     if (ctx->singlestep == 0) {
         tcg_gen_goto_tb(n);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 11/13] target-avr: Put all translation code into one compilation unit
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (9 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 10/13] target-avr: Put env pointer in DisasContext Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 12/13] target-avr: Respect .inc.c convention Richard Henderson
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/Makefile.objs    |   2 -
 target-avr/decode.c         |   6 +-
 target-avr/translate-inst.c | 198 ++++++++++++++++++++++----------------------
 target-avr/translate-inst.h | 113 -------------------------
 target-avr/translate.c      | 103 ++++++++++++++++++-----
 target-avr/translate.h      | 112 -------------------------
 6 files changed, 182 insertions(+), 352 deletions(-)
 delete mode 100644 target-avr/translate.h

diff --git a/target-avr/Makefile.objs b/target-avr/Makefile.objs
index 9848b1c..48233ef 100644
--- a/target-avr/Makefile.objs
+++ b/target-avr/Makefile.objs
@@ -20,6 +20,4 @@
 
 obj-y += translate.o cpu.o helper.o
 obj-y += gdbstub.o
-obj-y += translate-inst.o
-obj-y += decode.o
 obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-avr/decode.c b/target-avr/decode.c
index 2d2e54e..576dd83 100644
--- a/target-avr/decode.c
+++ b/target-avr/decode.c
@@ -18,10 +18,8 @@
  * <http://www.gnu.org/licenses/lgpl-2.1.html>
  */
 
-#include <stdint.h>
-#include "translate.h"
-
-void avr_decode(uint32_t pc, uint32_t *l, uint32_t c, translate_function_t *t)
+static void avr_decode(uint32_t pc, uint32_t *l, uint32_t c,
+                       translate_function_t *t)
 {
     uint32_t opc = extract32(c, 0, 16);
     switch (opc & 0x0000d000) {
diff --git a/target-avr/translate-inst.c b/target-avr/translate-inst.c
index 377263a..827ec7b 100644
--- a/target-avr/translate-inst.c
+++ b/target-avr/translate-inst.c
@@ -18,10 +18,6 @@
  *  <http://www.gnu.org/licenses/lgpl-2.1.html>
  */
 
-#include "translate.h"
-#include "translate-inst.h"
-#include "qemu/bitops.h"
-
 static void gen_add_CHf(TCGv R, TCGv Rd, TCGv Rr)
 {
     TCGv t1 = tcg_temp_new_i32();
@@ -249,7 +245,7 @@ static TCGv gen_get_zaddr(void)
  *  Adds two registers and the contents of the C Flag and places the result in
  *  the destination register Rd.
  */
-int avr_translate_ADC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ADC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[ADC_Rd(opcode)];
     TCGv Rr = cpu_r[ADC_Rr(opcode)];
@@ -276,7 +272,7 @@ int avr_translate_ADC(DisasContext *ctx, uint32_t opcode)
  *  Adds two registers without the C Flag and places the result in the
  *  destination register Rd.
  */
-int avr_translate_ADD(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ADD(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[ADD_Rd(opcode)];
     TCGv Rr = cpu_r[ADD_Rr(opcode)];
@@ -305,7 +301,7 @@ int avr_translate_ADD(DisasContext *ctx, uint32_t opcode)
  *  instruction is not available in all devices. Refer to the device specific
  *  instruction set summary.
  */
-int avr_translate_ADIW(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ADIW(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
         gen_helper_unsupported(cpu_env);
@@ -355,7 +351,7 @@ int avr_translate_ADIW(DisasContext *ctx, uint32_t opcode)
  *  Performs the logical AND between the contents of register Rd and register
  *  Rr and places the result in the destination register Rd.
  */
-int avr_translate_AND(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_AND(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[AND_Rd(opcode)];
     TCGv Rr = cpu_r[AND_Rr(opcode)];
@@ -384,7 +380,7 @@ int avr_translate_AND(DisasContext *ctx, uint32_t opcode)
  *  Performs the logical AND between the contents of register Rd and a constant
  *  and places the result in the destination register Rd.
  */
-int avr_translate_ANDI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ANDI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + ANDI_Rd(opcode)];
     int Imm = (ANDI_Imm(opcode));
@@ -404,7 +400,7 @@ int avr_translate_ANDI(DisasContext *ctx, uint32_t opcode)
  *  signed value by two without changing its sign. The Carry Flag can be used to
  *  round the result.
  */
-int avr_translate_ASR(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ASR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[ASR_Rd(opcode)];
     TCGv t1 = tcg_temp_new_i32();
@@ -435,7 +431,7 @@ int avr_translate_ASR(DisasContext *ctx, uint32_t opcode)
 /*
  *  Clears a single Flag in SREG.
  */
-int avr_translate_BCLR(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_BCLR(DisasContext *ctx, uint32_t opcode)
 {
     switch (BCLR_Bit(opcode)) {
     case 0x00:
@@ -470,7 +466,7 @@ int avr_translate_BCLR(DisasContext *ctx, uint32_t opcode)
 /*
  *  Copies the T Flag in the SREG (Status Register) to bit b in register Rd.
  */
-int avr_translate_BLD(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_BLD(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[BLD_Rd(opcode)];
     TCGv t1 = tcg_temp_new_i32();
@@ -491,7 +487,7 @@ int avr_translate_BLD(DisasContext *ctx, uint32_t opcode)
  *  parameter k is the offset from PC and is represented in two's complement
  *  form.
  */
-int avr_translate_BRBC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_BRBC(DisasContext *ctx, uint32_t opcode)
 {
     TCGLabel *taken = gen_new_label();
     int Imm = sextract32(BRBC_Imm(opcode), 0, 7);
@@ -536,7 +532,7 @@ int avr_translate_BRBC(DisasContext *ctx, uint32_t opcode)
  *  PC in either direction (PC - 63 < = destination <= PC + 64). The parameter k
  *  is the offset from PC and is represented in two's complement form.
  */
-int avr_translate_BRBS(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_BRBS(DisasContext *ctx, uint32_t opcode)
 {
     TCGLabel *taken = gen_new_label();
     int Imm = sextract32(BRBS_Imm(opcode), 0, 7);
@@ -578,7 +574,7 @@ int avr_translate_BRBS(DisasContext *ctx, uint32_t opcode)
 /*
  *  Sets a single Flag or bit in SREG.
  */
-int avr_translate_BSET(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_BSET(DisasContext *ctx, uint32_t opcode)
 {
     switch (BSET_Bit(opcode)) {
     case 0x00:
@@ -620,7 +616,7 @@ int avr_translate_BSET(DisasContext *ctx, uint32_t opcode)
  *  is not available in all devices. Refer to the device specific instruction
  *  set summary.
  */
-int avr_translate_BREAK(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_BREAK(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_BREAK) == false) {
         gen_helper_unsupported(cpu_env);
@@ -635,7 +631,7 @@ int avr_translate_BREAK(DisasContext *ctx, uint32_t opcode)
 /*
  *  Stores bit b from Rd to the T Flag in SREG (Status Register).
  */
-int avr_translate_BST(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_BST(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[BST_Rd(opcode)];
 
@@ -652,7 +648,7 @@ int avr_translate_BST(DisasContext *ctx, uint32_t opcode)
  *  CALL.  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_CALL(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_CALL(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_JMP_CALL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -673,7 +669,7 @@ int avr_translate_CALL(DisasContext *ctx, uint32_t opcode)
  *  Clears a specified bit in an I/O Register. This instruction operates on
  *  the lower 32 I/O Registers -- addresses 0-31.
  */
-int avr_translate_CBI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_CBI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv data = tcg_temp_new_i32();
     TCGv port = tcg_const_i32(CBI_Imm(opcode));
@@ -693,7 +689,7 @@ int avr_translate_CBI(DisasContext *ctx, uint32_t opcode)
  *  between the contents of register Rd and the complement of the constant mask
  *  K. The result will be placed in register Rd.
  */
-int avr_translate_COM(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_COM(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[COM_Rd(opcode)];
     TCGv R = tcg_temp_new_i32();
@@ -714,7 +710,7 @@ int avr_translate_COM(DisasContext *ctx, uint32_t opcode)
  *  None of the registers are changed. All conditional branches can be used
  *  after this instruction.
  */
-int avr_translate_CP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_CP(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[CP_Rd(opcode)];
     TCGv Rr = cpu_r[CP_Rr(opcode)];
@@ -738,7 +734,7 @@ int avr_translate_CP(DisasContext *ctx, uint32_t opcode)
  *  also takes into account the previous carry. None of the registers are
  *  changed. All conditional branches can be used after this instruction.
  */
-int avr_translate_CPC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_CPC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[CPC_Rd(opcode)];
     TCGv Rr = cpu_r[CPC_Rr(opcode)];
@@ -768,7 +764,7 @@ int avr_translate_CPC(DisasContext *ctx, uint32_t opcode)
  *  The register is not changed. All conditional branches can be used after this
  *  instruction.
  */
-int avr_translate_CPI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_CPI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + CPI_Rd(opcode)];
     int Imm = CPI_Imm(opcode);
@@ -793,7 +789,7 @@ int avr_translate_CPI(DisasContext *ctx, uint32_t opcode)
  *  This instruction performs a compare between two registers Rd and Rr, and
  *  skips the next instruction if Rd = Rr.
  */
-int avr_translate_CPSE(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_CPSE(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[CPSE_Rd(opcode)];
     TCGv Rr = cpu_r[CPSE_Rr(opcode)];
@@ -817,7 +813,7 @@ int avr_translate_CPSE(DisasContext *ctx, uint32_t opcode)
  *  BREQ and BRNE branches can be expected to perform consistently.  When
  *  operating on two's complement values, all signed branches are available.
  */
-int avr_translate_DEC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_DEC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[DEC_Rd(opcode)];
 
@@ -851,7 +847,7 @@ int avr_translate_DEC(DisasContext *ctx, uint32_t opcode)
  *  affect the result in the final ciphertext or plaintext, but reduces
  *  execution time.
  */
-int avr_translate_DES(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_DES(DisasContext *ctx, uint32_t opcode)
 {
     /* TODO: */
     if (avr_feature(ctx->env, AVR_FEATURE_DES) == false) {
@@ -871,7 +867,7 @@ int avr_translate_DES(DisasContext *ctx, uint32_t opcode)
  *  during EICALL.  This instruction is not available in all devices. Refer to
  *  the device specific instruction set summary.
  */
-int avr_translate_EICALL(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_EICALL(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_EIJMP_EICALL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -895,7 +891,7 @@ int avr_translate_EICALL(DisasContext *ctx, uint32_t opcode)
  *  memory space. See also IJMP.  This instruction is not available in all
  *  devices. Refer to the device specific instruction set summary.
  */
-int avr_translate_EIJMP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_EIJMP(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_EIJMP_EICALL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -924,7 +920,7 @@ int avr_translate_EIJMP(DisasContext *ctx, uint32_t opcode)
  *  instruction is not available in all devices. Refer to the device specific
  *  instruction set summary.
  */
-int avr_translate_ELPM1(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ELPM1(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_ELPM) == false) {
         gen_helper_unsupported(cpu_env);
@@ -942,7 +938,7 @@ int avr_translate_ELPM1(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_ELPM2(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ELPM2(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_ELPM) == false) {
         gen_helper_unsupported(cpu_env);
@@ -960,7 +956,7 @@ int avr_translate_ELPM2(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_ELPMX(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ELPMX(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_ELPMX) == false) {
         gen_helper_unsupported(cpu_env);
@@ -986,7 +982,7 @@ int avr_translate_ELPMX(DisasContext *ctx, uint32_t opcode)
  *  Performs the logical EOR between the contents of register Rd and
  *  register Rr and places the result in the destination register Rd.
  */
-int avr_translate_EOR(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_EOR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[EOR_Rd(opcode)];
     TCGv Rr = cpu_r[EOR_Rr(opcode)];
@@ -1003,7 +999,7 @@ int avr_translate_EOR(DisasContext *ctx, uint32_t opcode)
  *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned
  *  multiplication and shifts the result one bit left.
  */
-int avr_translate_FMUL(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_FMUL(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1036,7 +1032,7 @@ int avr_translate_FMUL(DisasContext *ctx, uint32_t opcode)
  *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
  *  and shifts the result one bit left.
  */
-int avr_translate_FMULS(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_FMULS(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1075,7 +1071,7 @@ int avr_translate_FMULS(DisasContext *ctx, uint32_t opcode)
  *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
  *  and shifts the result one bit left.
  */
-int avr_translate_FMULSU(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_FMULSU(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1114,7 +1110,7 @@ int avr_translate_FMULSU(DisasContext *ctx, uint32_t opcode)
  *  CALL.  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_ICALL(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ICALL(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_IJMP_ICALL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1137,7 +1133,7 @@ int avr_translate_ICALL(DisasContext *ctx, uint32_t opcode)
  *  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_IJMP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_IJMP(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_IJMP_ICALL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1154,7 +1150,7 @@ int avr_translate_IJMP(DisasContext *ctx, uint32_t opcode)
  *  Loads data from the I/O Space (Ports, Timers, Configuration Registers,
  *  etc.) into register Rd in the Register File.
  */
-int avr_translate_IN(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_IN(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[IN_Rd(opcode)];
     int Imm = IN_Imm(opcode);
@@ -1175,7 +1171,7 @@ int avr_translate_IN(DisasContext *ctx, uint32_t opcode)
  *  BREQ and BRNE branches can be expected to perform consistently. When
  *  operating on two's complement values, all signed branches are available.
  */
-int avr_translate_INC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_INC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[INC_Rd(opcode)];
 
@@ -1193,7 +1189,7 @@ int avr_translate_INC(DisasContext *ctx, uint32_t opcode)
  *  RJMP.  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.0
  */
-int avr_translate_JMP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_JMP(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_JMP_CALL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1233,7 +1229,7 @@ static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr)
     }
 }
 
-int avr_translate_LAC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LAC(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1270,7 +1266,7 @@ int avr_translate_LAC(DisasContext *ctx, uint32_t opcode)
  *  The Z-pointer Register is left unchanged by the operation. This instruction
  *  is especially suited for setting status bits stored in SRAM.
  */
-int avr_translate_LAS(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LAS(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1306,7 +1302,7 @@ int avr_translate_LAS(DisasContext *ctx, uint32_t opcode)
  *  The Z-pointer Register is left unchanged by the operation. This instruction
  *  is especially suited for changing status bits stored in SRAM.
  */
-int avr_translate_LAT(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LAT(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1357,7 +1353,7 @@ int avr_translate_LAT(DisasContext *ctx, uint32_t opcode)
  *  operation as LPM since the program memory is mapped to the data memory
  *  space.
  */
-int avr_translate_LDX1(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDX1(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDX1_Rd(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -1369,7 +1365,7 @@ int avr_translate_LDX1(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDX2(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDX2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDX2_Rd(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -1384,7 +1380,7 @@ int avr_translate_LDX2(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDX3(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDX3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDX3_Rd(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -1423,7 +1419,7 @@ int avr_translate_LDX3(DisasContext *ctx, uint32_t opcode)
  *  be used to achieve the same operation as LPM since the program memory is
  *  mapped to the data memory space.
  */
-int avr_translate_LDY2(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDY2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDY2_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -1438,7 +1434,7 @@ int avr_translate_LDY2(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDY3(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDY3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDY3_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -1452,7 +1448,7 @@ int avr_translate_LDY3(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDDY(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDDY(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDDY_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -1494,7 +1490,7 @@ int avr_translate_LDDY(DisasContext *ctx, uint32_t opcode)
  *  space.  For using the Z-pointer for table lookup in Program memory see the
  *  LPM and ELPM instructions.
  */
-int avr_translate_LDZ2(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDZ2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDZ2_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -1509,7 +1505,7 @@ int avr_translate_LDZ2(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDZ3(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDZ3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDZ3_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -1524,7 +1520,7 @@ int avr_translate_LDZ3(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LDDZ(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDDZ(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDDZ_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -1541,7 +1537,7 @@ int avr_translate_LDDZ(DisasContext *ctx, uint32_t opcode)
 /*
     Loads an 8 bit constant directly to register 16 to 31.
  */
-int avr_translate_LDI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + LDI_Rd(opcode)];
     int imm = LDI_Imm(opcode);
@@ -1563,7 +1559,7 @@ int avr_translate_LDI(DisasContext *ctx, uint32_t opcode)
  *  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_LDS(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LDS(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LDS_Rd(opcode)];
     TCGv addr = tcg_temp_new_i32();
@@ -1595,7 +1591,7 @@ int avr_translate_LDS(DisasContext *ctx, uint32_t opcode)
  *  available in all devices. Refer to the device specific instruction set
  *  summary
  */
-int avr_translate_LPM1(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LPM1(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_LPM) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1618,7 +1614,7 @@ int avr_translate_LPM1(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LPM2(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LPM2(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_LPM) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1641,7 +1637,7 @@ int avr_translate_LPM2(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_LPMX(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LPMX(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_LPMX) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1676,7 +1672,7 @@ int avr_translate_LPMX(DisasContext *ctx, uint32_t opcode)
  *  loaded into the C Flag of the SREG. This operation effectively divides an
  *  unsigned value by two. The C Flag can be used to round the result.
  */
-int avr_translate_LSR(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_LSR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[LSR_Rd(opcode)];
 
@@ -1694,7 +1690,7 @@ int avr_translate_LSR(DisasContext *ctx, uint32_t opcode)
  *  register Rr is left unchanged, while the destination register Rd is loaded
  *  with a copy of Rr.
  */
-int avr_translate_MOV(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_MOV(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[MOV_Rd(opcode)];
     TCGv Rr = cpu_r[MOV_Rr(opcode)];
@@ -1711,7 +1707,7 @@ int avr_translate_MOV(DisasContext *ctx, uint32_t opcode)
  *  instruction is not available in all devices. Refer to the device specific
  *  instruction set summary.
  */
-int avr_translate_MOVW(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_MOVW(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_MOVW) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1733,7 +1729,7 @@ int avr_translate_MOVW(DisasContext *ctx, uint32_t opcode)
 /*
  *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication.
  */
-int avr_translate_MUL(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_MUL(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1765,7 +1761,7 @@ int avr_translate_MUL(DisasContext *ctx, uint32_t opcode)
 /*
  *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication.
  */
-int avr_translate_MULS(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_MULS(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1805,7 +1801,7 @@ int avr_translate_MULS(DisasContext *ctx, uint32_t opcode)
  *  This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a
  *  signed and an unsigned number.
  */
-int avr_translate_MULSU(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_MULSU(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
         gen_helper_unsupported(cpu_env);
@@ -1842,7 +1838,7 @@ int avr_translate_MULSU(DisasContext *ctx, uint32_t opcode)
  *  Replaces the contents of register Rd with its two's complement; the
  *  value $80 is left unchanged.
  */
-int avr_translate_NEG(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_NEG(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[SUB_Rd(opcode)];
     TCGv t0 = tcg_const_i32(0);
@@ -1868,7 +1864,7 @@ int avr_translate_NEG(DisasContext *ctx, uint32_t opcode)
 /*
  *  This instruction performs a single cycle No Operation.
  */
-int avr_translate_NOP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_NOP(DisasContext *ctx, uint32_t opcode)
 {
 
     /* NOP */
@@ -1880,7 +1876,7 @@ int avr_translate_NOP(DisasContext *ctx, uint32_t opcode)
  *  Performs the logical OR between the contents of register Rd and register
  *  Rr and places the result in the destination register Rd.
  */
-int avr_translate_OR(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_OR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[OR_Rd(opcode)];
     TCGv Rr = cpu_r[OR_Rr(opcode)];
@@ -1900,7 +1896,7 @@ int avr_translate_OR(DisasContext *ctx, uint32_t opcode)
  *  Performs the logical OR between the contents of register Rd and a
  *  constant and places the result in the destination register Rd.
  */
-int avr_translate_ORI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ORI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + ORI_Rd(opcode)];
     int Imm = (ORI_Imm(opcode));
@@ -1917,7 +1913,7 @@ int avr_translate_ORI(DisasContext *ctx, uint32_t opcode)
  *  Stores data from register Rr in the Register File to I/O Space (Ports,
  *  Timers, Configuration Registers, etc.).
  */
-int avr_translate_OUT(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_OUT(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[OUT_Rd(opcode)];
     int Imm = OUT_Imm(opcode);
@@ -1936,7 +1932,7 @@ int avr_translate_OUT(DisasContext *ctx, uint32_t opcode)
  *  available in all devices. Refer to the device specific instruction set
  *  summary.
  */
-int avr_translate_POP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_POP(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[POP_Rd(opcode)];
 
@@ -1952,7 +1948,7 @@ int avr_translate_POP(DisasContext *ctx, uint32_t opcode)
  *  not available in all devices. Refer to the device specific instruction set
  *  summary.
  */
-int avr_translate_PUSH(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_PUSH(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[PUSH_Rd(opcode)];
 
@@ -1970,7 +1966,7 @@ int avr_translate_PUSH(DisasContext *ctx, uint32_t opcode)
  *  address location. The Stack Pointer uses a post-decrement scheme during
  *  RCALL.
  */
-int avr_translate_RCALL(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_RCALL(DisasContext *ctx, uint32_t opcode)
 {
     int ret = ctx->inst[0].npc;
     int dst = ctx->inst[0].npc + sextract32(RCALL_Imm(opcode), 0, 12);
@@ -1985,7 +1981,7 @@ int avr_translate_RCALL(DisasContext *ctx, uint32_t opcode)
  *  Returns from subroutine. The return address is loaded from the STACK.
  *  The Stack Pointer uses a preincrement scheme during RET.
  */
-int avr_translate_RET(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_RET(DisasContext *ctx, uint32_t opcode)
 {
     gen_pop_ret(ctx, cpu_pc);
 
@@ -2002,7 +1998,7 @@ int avr_translate_RET(DisasContext *ctx, uint32_t opcode)
  *  the application program. The Stack Pointer uses a pre-increment scheme
  *  during RETI.
  */
-int avr_translate_RETI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_RETI(DisasContext *ctx, uint32_t opcode)
 {
     gen_pop_ret(ctx, cpu_pc);
 
@@ -2019,7 +2015,7 @@ int avr_translate_RETI(DisasContext *ctx, uint32_t opcode)
  *  instruction can address the entire memory from every address location. See
  *  also JMP.
  */
-int avr_translate_RJMP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_RJMP(DisasContext *ctx, uint32_t opcode)
 {
     int dst = ctx->inst[0].npc + sextract32(RJMP_Imm(opcode), 0, 12);
 
@@ -2035,7 +2031,7 @@ int avr_translate_RJMP(DisasContext *ctx, uint32_t opcode)
  *  LSR it effectively divides multi-byte unsigned values by two. The Carry Flag
  *  can be used to round the result.
  */
-int avr_translate_ROR(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_ROR(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[ROR_Rd(opcode)];
     TCGv t0 = tcg_temp_new_i32();
@@ -2057,7 +2053,7 @@ int avr_translate_ROR(DisasContext *ctx, uint32_t opcode)
  *  Subtracts two registers and subtracts with the C Flag and places the
  *  result in the destination register Rd.
  */
-int avr_translate_SBC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SBC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[SBC_Rd(opcode)];
     TCGv Rr = cpu_r[SBC_Rr(opcode)];
@@ -2083,7 +2079,7 @@ int avr_translate_SBC(DisasContext *ctx, uint32_t opcode)
 /*
  *  SBCI -- Subtract Immediate with Carry
  */
-int avr_translate_SBCI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SBCI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + SBCI_Rd(opcode)];
     TCGv Rr = tcg_const_i32(SBCI_Imm(opcode));
@@ -2111,7 +2107,7 @@ int avr_translate_SBCI(DisasContext *ctx, uint32_t opcode)
  *  Sets a specified bit in an I/O Register. This instruction operates on
  *  the lower 32 I/O Registers -- addresses 0-31.
  */
-int avr_translate_SBI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SBI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv data = tcg_temp_new_i32();
     TCGv port = tcg_const_i32(SBI_Imm(opcode));
@@ -2131,7 +2127,7 @@ int avr_translate_SBI(DisasContext *ctx, uint32_t opcode)
  *  next instruction if the bit is cleared. This instruction operates on the
  *  lower 32 I/O Registers -- addresses 0-31.
  */
-int avr_translate_SBIC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SBIC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv data = tcg_temp_new_i32();
     TCGv port = tcg_const_i32(SBIC_Imm(opcode));
@@ -2158,7 +2154,7 @@ int avr_translate_SBIC(DisasContext *ctx, uint32_t opcode)
  *  next instruction if the bit is set. This instruction operates on the lower
  *  32 I/O Registers -- addresses 0-31.
  */
-int avr_translate_SBIS(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SBIS(DisasContext *ctx, uint32_t opcode)
 {
     TCGv data = tcg_temp_new_i32();
     TCGv port = tcg_const_i32(SBIS_Imm(opcode));
@@ -2187,7 +2183,7 @@ int avr_translate_SBIS(DisasContext *ctx, uint32_t opcode)
  *  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_SBIW(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SBIW(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
         gen_helper_unsupported(cpu_env);
@@ -2237,7 +2233,7 @@ int avr_translate_SBIW(DisasContext *ctx, uint32_t opcode)
  *  This instruction tests a single bit in a register and skips the next
  *  instruction if the bit is cleared.
  */
-int avr_translate_SBRC(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SBRC(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rr = cpu_r[SBRC_Rr(opcode)];
     TCGv t0 = tcg_temp_new_i32();
@@ -2260,7 +2256,7 @@ int avr_translate_SBRC(DisasContext *ctx, uint32_t opcode)
  *  This instruction tests a single bit in a register and skips the next
  *  instruction if the bit is set.
  */
-int avr_translate_SBRS(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SBRS(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rr = cpu_r[SBRS_Rr(opcode)];
     TCGv t0 = tcg_temp_new_i32();
@@ -2283,7 +2279,7 @@ int avr_translate_SBRS(DisasContext *ctx, uint32_t opcode)
  *  This instruction sets the circuit in sleep mode defined by the MCU
  *  Control Register.
  */
-int avr_translate_SLEEP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SLEEP(DisasContext *ctx, uint32_t opcode)
 {
     gen_helper_sleep(cpu_env);
 
@@ -2307,7 +2303,7 @@ int avr_translate_SLEEP(DisasContext *ctx, uint32_t opcode)
  *  determines the instruction high byte, and R0 determines the instruction low
  *  byte.
  */
-int avr_translate_SPM(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SPM(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_SPM) == false) {
         gen_helper_unsupported(cpu_env);
@@ -2319,7 +2315,7 @@ int avr_translate_SPM(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_SPMX(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SPMX(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_SPMX) == false) {
         gen_helper_unsupported(cpu_env);
@@ -2331,7 +2327,7 @@ int avr_translate_SPMX(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STX1(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STX1(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STX1_Rr(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -2343,7 +2339,7 @@ int avr_translate_STX1(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STX2(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STX2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STX2_Rr(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -2357,7 +2353,7 @@ int avr_translate_STX2(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STX3(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STX3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STX3_Rr(opcode)];
     TCGv addr = gen_get_xaddr();
@@ -2371,7 +2367,7 @@ int avr_translate_STX3(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STY2(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STY2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STY2_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -2385,7 +2381,7 @@ int avr_translate_STY2(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STY3(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STY3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STY3_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -2399,7 +2395,7 @@ int avr_translate_STY3(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STDY(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STDY(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STDY_Rd(opcode)];
     TCGv addr = gen_get_yaddr();
@@ -2413,7 +2409,7 @@ int avr_translate_STDY(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STZ2(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STZ2(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STZ2_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -2428,7 +2424,7 @@ int avr_translate_STZ2(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STZ3(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STZ3(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STZ3_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -2443,7 +2439,7 @@ int avr_translate_STZ3(DisasContext *ctx, uint32_t opcode)
     return BS_NONE;
 }
 
-int avr_translate_STDZ(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STDZ(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STDZ_Rd(opcode)];
     TCGv addr = gen_get_zaddr();
@@ -2469,7 +2465,7 @@ int avr_translate_STDZ(DisasContext *ctx, uint32_t opcode)
  *  This instruction is not available in all devices. Refer to the device
  *  specific instruction set summary.
  */
-int avr_translate_STS(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_STS(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[STS_Rd(opcode)];
     TCGv addr = tcg_temp_new_i32();
@@ -2490,7 +2486,7 @@ int avr_translate_STS(DisasContext *ctx, uint32_t opcode)
  *  Subtracts two registers and places the result in the destination
  *  register Rd.
  */
-int avr_translate_SUB(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SUB(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[SUB_Rd(opcode)];
     TCGv Rr = cpu_r[SUB_Rr(opcode)];
@@ -2517,7 +2513,7 @@ int avr_translate_SUB(DisasContext *ctx, uint32_t opcode)
  *  destination register Rd. This instruction is working on Register R16 to R31
  *  and is very well suited for operations on the X, Y, and Z-pointers.
  */
-int avr_translate_SUBI(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SUBI(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[16 + SUBI_Rd(opcode)];
     TCGv Rr = tcg_const_i32(SUBI_Imm(opcode));
@@ -2544,7 +2540,7 @@ int avr_translate_SUBI(DisasContext *ctx, uint32_t opcode)
 /*
  *  Swaps high and low nibbles in a register.
  */
-int avr_translate_SWAP(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_SWAP(DisasContext *ctx, uint32_t opcode)
 {
     TCGv Rd = cpu_r[SWAP_Rd(opcode)];
     TCGv t0 = tcg_temp_new_i32();
@@ -2567,7 +2563,7 @@ int avr_translate_SWAP(DisasContext *ctx, uint32_t opcode)
  *  executed within a limited time given by the WD prescaler. See the Watchdog
  *  Timer hardware specification.
  */
-int avr_translate_WDR(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_WDR(DisasContext *ctx, uint32_t opcode)
 {
     gen_helper_wdr(cpu_env);
 
@@ -2583,7 +2579,7 @@ int avr_translate_WDR(DisasContext *ctx, uint32_t opcode)
  *  is left unchanged by the operation. This instruction is especially suited
  *  for writing/reading status bits stored in SRAM.
  */
-int avr_translate_XCH(DisasContext *ctx, uint32_t opcode)
+static int avr_translate_XCH(DisasContext *ctx, uint32_t opcode)
 {
     if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
         gen_helper_unsupported(cpu_env);
diff --git a/target-avr/translate-inst.h b/target-avr/translate-inst.h
index 47b0a3e..7371c6f 100644
--- a/target-avr/translate-inst.h
+++ b/target-avr/translate-inst.h
@@ -21,11 +21,6 @@
 #ifndef AVR_TRANSLATE_INST_H_
 #define AVR_TRANSLATE_INST_H_
 
-typedef struct DisasContext DisasContext;
-
-int avr_translate_NOP(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_MOVW(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MOVW_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 4);
@@ -36,7 +31,6 @@ static inline uint32_t MOVW_Rd(uint32_t opcode)
     return extract32(opcode, 4, 4);
 }
 
-int avr_translate_MULS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MULS_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 4);
@@ -47,7 +41,6 @@ static inline uint32_t MULS_Rd(uint32_t opcode)
     return extract32(opcode, 4, 4);
 }
 
-int avr_translate_MULSU(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MULSU_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -58,7 +51,6 @@ static inline uint32_t MULSU_Rd(uint32_t opcode)
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_FMUL(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t FMUL_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -69,7 +61,6 @@ static inline uint32_t FMUL_Rd(uint32_t opcode)
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_FMULS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t FMULS_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -80,7 +71,6 @@ static inline uint32_t FMULS_Rd(uint32_t opcode)
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_FMULSU(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t FMULSU_Rr(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -91,7 +81,6 @@ static inline uint32_t FMULSU_Rd(uint32_t opcode)
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_CPC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CPC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -103,7 +92,6 @@ static inline uint32_t CPC_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SBC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -115,7 +103,6 @@ static inline uint32_t SBC_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_ADD(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ADD_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -127,7 +114,6 @@ static inline uint32_t ADD_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_AND(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t AND_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -139,7 +125,6 @@ static inline uint32_t AND_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_EOR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t EOR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -151,7 +136,6 @@ static inline uint32_t EOR_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_OR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t OR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -163,7 +147,6 @@ static inline uint32_t OR_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_MOV(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MOV_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -175,7 +158,6 @@ static inline uint32_t MOV_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_CPSE(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CPSE_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -187,7 +169,6 @@ static inline uint32_t CPSE_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_CP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CP_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -199,7 +180,6 @@ static inline uint32_t CP_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SUB(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SUB_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -211,7 +191,6 @@ static inline uint32_t SUB_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_ADC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ADC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -223,7 +202,6 @@ static inline uint32_t ADC_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_CPI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CPI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -235,7 +213,6 @@ static inline uint32_t CPI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SBCI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBCI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -247,7 +224,6 @@ static inline uint32_t SBCI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_ORI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ORI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -259,7 +235,6 @@ static inline uint32_t ORI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SUBI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SUBI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -271,7 +246,6 @@ static inline uint32_t SUBI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_ANDI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ANDI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -283,7 +257,6 @@ static inline uint32_t ANDI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_LDDZ(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDDZ_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -296,7 +269,6 @@ static inline uint32_t LDDZ_Imm(uint32_t opcode)
             (extract32(opcode, 0, 3));
 }
 
-int avr_translate_LDDY(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDDY_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -309,7 +281,6 @@ static inline uint32_t LDDY_Imm(uint32_t opcode)
             (extract32(opcode, 0, 3));
 }
 
-int avr_translate_STDZ(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STDZ_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -322,7 +293,6 @@ static inline uint32_t STDZ_Imm(uint32_t opcode)
             (extract32(opcode, 0, 3));
 }
 
-int avr_translate_STDY(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STDY_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -335,7 +305,6 @@ static inline uint32_t STDY_Imm(uint32_t opcode)
             (extract32(opcode, 0, 3));
 }
 
-int avr_translate_LDS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDS_Imm(uint32_t opcode)
 {
     return extract32(opcode, 0, 16);
@@ -346,79 +315,66 @@ static inline uint32_t LDS_Rd(uint32_t opcode)
     return extract32(opcode, 20, 5);
 }
 
-int avr_translate_LDZ2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDZ2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDZ3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDZ3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LPM2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LPM2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LPMX(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LPMX_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_ELPM2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ELPM2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_ELPMX(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ELPMX_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDY2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDY2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDY3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDY3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDX1(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDX1_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDX2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDX2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LDX3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDX3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_POP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t POP_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STS_Imm(uint32_t opcode)
 {
     return extract32(opcode, 0, 16);
@@ -429,185 +385,133 @@ static inline uint32_t STS_Rd(uint32_t opcode)
     return extract32(opcode, 20, 5);
 }
 
-int avr_translate_STZ2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STZ2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STZ3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STZ3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_XCH(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t XCH_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LAS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LAS_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LAC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LAC_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LAT(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LAT_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STY2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STY2_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STY3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STY3_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STX1(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STX1_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STX2(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STX2_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_STX3(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t STX3_Rr(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_PUSH(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t PUSH_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_COM(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t COM_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_NEG(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t NEG_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_SWAP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SWAP_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_INC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t INC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_ASR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ASR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_LSR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LSR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_ROR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ROR_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_BSET(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BSET_Bit(uint32_t opcode)
 {
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_IJMP(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_EIJMP(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_BCLR(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BCLR_Bit(uint32_t opcode)
 {
     return extract32(opcode, 4, 3);
 }
 
-int avr_translate_RET(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_RETI(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_ICALL(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_EICALL(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_SLEEP(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_BREAK(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_WDR(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_LPM1(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_ELPM1(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_SPM(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_SPMX(DisasContext* ctx, uint32_t opcode);
-
-int avr_translate_DEC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t DEC_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_DES(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t DES_Imm(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
 }
 
-int avr_translate_JMP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t JMP_Imm(uint32_t opcode)
 {
     return (extract32(opcode, 20, 5) << 17) |
             (extract32(opcode, 0, 17));
 }
 
-int avr_translate_CALL(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CALL_Imm(uint32_t opcode)
 {
     return (extract32(opcode, 20, 5) << 17) |
             (extract32(opcode, 0, 17));
 }
 
-int avr_translate_ADIW(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t ADIW_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 2);
@@ -619,7 +523,6 @@ static inline uint32_t ADIW_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_SBIW(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBIW_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 2);
@@ -631,7 +534,6 @@ static inline uint32_t SBIW_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_CBI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t CBI_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -642,7 +544,6 @@ static inline uint32_t CBI_Imm(uint32_t opcode)
     return extract32(opcode, 3, 5);
 }
 
-int avr_translate_SBIC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBIC_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -653,7 +554,6 @@ static inline uint32_t SBIC_Imm(uint32_t opcode)
     return extract32(opcode, 3, 5);
 }
 
-int avr_translate_SBI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBI_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -664,7 +564,6 @@ static inline uint32_t SBI_Imm(uint32_t opcode)
     return extract32(opcode, 3, 5);
 }
 
-int avr_translate_SBIS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBIS_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -675,7 +574,6 @@ static inline uint32_t SBIS_Imm(uint32_t opcode)
     return extract32(opcode, 3, 5);
 }
 
-int avr_translate_MUL(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t MUL_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -687,7 +585,6 @@ static inline uint32_t MUL_Rr(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_IN(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t IN_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -699,7 +596,6 @@ static inline uint32_t IN_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_OUT(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t OUT_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 5);
@@ -711,13 +607,11 @@ static inline uint32_t OUT_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_RJMP(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t RJMP_Imm(uint32_t opcode)
 {
     return extract32(opcode, 0, 12);
 }
 
-int avr_translate_LDI(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t LDI_Rd(uint32_t opcode)
 {
     return extract32(opcode, 4, 4);
@@ -729,13 +623,11 @@ static inline uint32_t LDI_Imm(uint32_t opcode)
             (extract32(opcode, 0, 4));
 }
 
-int avr_translate_RCALL(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t RCALL_Imm(uint32_t opcode)
 {
     return extract32(opcode, 0, 12);
 }
 
-int avr_translate_BRBS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BRBS_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -746,7 +638,6 @@ static inline uint32_t BRBS_Imm(uint32_t opcode)
     return extract32(opcode, 3, 7);
 }
 
-int avr_translate_BRBC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BRBC_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -757,7 +648,6 @@ static inline uint32_t BRBC_Imm(uint32_t opcode)
     return extract32(opcode, 3, 7);
 }
 
-int avr_translate_BLD(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BLD_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -768,7 +658,6 @@ static inline uint32_t BLD_Rd(uint32_t opcode)
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_BST(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t BST_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -779,7 +668,6 @@ static inline uint32_t BST_Rd(uint32_t opcode)
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_SBRC(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBRC_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
@@ -790,7 +678,6 @@ static inline uint32_t SBRC_Rr(uint32_t opcode)
     return extract32(opcode, 4, 5);
 }
 
-int avr_translate_SBRS(DisasContext* ctx, uint32_t opcode);
 static inline uint32_t SBRS_Bit(uint32_t opcode)
 {
     return extract32(opcode, 0, 3);
diff --git a/target-avr/translate.c b/target-avr/translate.c
index 51471fc..cb99b49 100644
--- a/target-avr/translate.c
+++ b/target-avr/translate.c
@@ -18,32 +18,95 @@
  * <http://www.gnu.org/licenses/lgpl-2.1.html>
  */
 
-#include "translate.h"
 
-TCGv_env cpu_env;
+#include "qemu/osdep.h"
+#include "tcg/tcg.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "disas/disas.h"
+#include "tcg-op.h"
+#include "exec/cpu_ldst.h"
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+#include "exec/log.h"
+
+static TCGv_env cpu_env;
+
+static TCGv cpu_pc;
+
+static TCGv cpu_Cf;
+static TCGv cpu_Zf;
+static TCGv cpu_Nf;
+static TCGv cpu_Vf;
+static TCGv cpu_Sf;
+static TCGv cpu_Hf;
+static TCGv cpu_Tf;
+static TCGv cpu_If;
+
+static TCGv cpu_rampD;
+static TCGv cpu_rampX;
+static TCGv cpu_rampY;
+static TCGv cpu_rampZ;
+
+static TCGv cpu_r[32];
+static TCGv cpu_eind;
+static TCGv cpu_sp;
 
-TCGv cpu_pc;
-
-TCGv cpu_Cf;
-TCGv cpu_Zf;
-TCGv cpu_Nf;
-TCGv cpu_Vf;
-TCGv cpu_Sf;
-TCGv cpu_Hf;
-TCGv cpu_Tf;
-TCGv cpu_If;
+#define REG(x) (cpu_r[x])
 
-TCGv cpu_rampD;
-TCGv cpu_rampX;
-TCGv cpu_rampY;
-TCGv cpu_rampZ;
+enum {
+    BS_NONE = 0, /* Nothing special (none of the below) */
+    BS_STOP = 1, /* We want to stop translation for any reason */
+    BS_BRANCH = 2, /* A branch condition is reached */
+    BS_EXCP = 3, /* An exception condition is reached */
+};
+
+uint32_t get_opcode(uint8_t const *code, unsigned bitBase, unsigned bitSize);
+
+typedef struct DisasContext DisasContext;
+typedef struct InstInfo InstInfo;
+
+typedef int (*translate_function_t)(DisasContext *ctx, uint32_t opcode);
+struct InstInfo {
+    target_long cpc;
+    target_long npc;
+    uint32_t opcode;
+    translate_function_t translate;
+    unsigned length;
+};
+
+/* This is the state at translation time. */
+struct DisasContext {
+    struct TranslationBlock *tb;
+    CPUAVRState *env;
+
+    InstInfo inst[2];/* two consecutive instructions */
+
+    /* Routine used to access memory */
+    int memidx;
+    int bstate;
+    int singlestep;
+};
+
+static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+{
+    TranslationBlock *tb = ctx->tb;
 
-TCGv cpu_r[32];
-TCGv cpu_eind;
-TCGv cpu_sp;
+    if (ctx->singlestep == 0) {
+        tcg_gen_goto_tb(n);
+        tcg_gen_movi_i32(cpu_pc, dest);
+        tcg_gen_exit_tb((uintptr_t)tb + n);
+    } else {
+        tcg_gen_movi_i32(cpu_pc, dest);
+        gen_helper_debug(cpu_env);
+        tcg_gen_exit_tb(0);
+    }
+}
 
 #include "exec/gen-icount.h"
-#define REG(x) (cpu_r[x])
+#include "translate-inst.h"
+#include "translate-inst.c"
+#include "decode.c"
 
 void avr_translate_init(void)
 {
diff --git a/target-avr/translate.h b/target-avr/translate.h
deleted file mode 100644
index fabbe69..0000000
--- a/target-avr/translate.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * QEMU AVR CPU
- *
- * Copyright (c) 2016 Michael Rolnik
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/lgpl-2.1.html>
- */
-
-#ifndef AVR_TRANSLATE_H_
-#define AVR_TRANSLATE_H_
-
-#include "qemu/osdep.h"
-
-#include "tcg/tcg.h"
-#include "cpu.h"
-#include "exec/exec-all.h"
-#include "disas/disas.h"
-#include "tcg-op.h"
-#include "exec/cpu_ldst.h"
-
-#include "exec/helper-proto.h"
-#include "exec/helper-gen.h"
-#include "exec/log.h"
-#include "translate-inst.h"
-
-extern TCGv_env cpu_env;
-
-extern TCGv cpu_pc;
-
-extern TCGv cpu_Cf;
-extern TCGv cpu_Zf;
-extern TCGv cpu_Nf;
-extern TCGv cpu_Vf;
-extern TCGv cpu_Sf;
-extern TCGv cpu_Hf;
-extern TCGv cpu_Tf;
-extern TCGv cpu_If;
-
-extern TCGv cpu_rampD;
-extern TCGv cpu_rampX;
-extern TCGv cpu_rampY;
-extern TCGv cpu_rampZ;
-
-extern TCGv cpu_r[32];
-extern TCGv cpu_eind;
-extern TCGv cpu_sp;
-
-enum {
-    BS_NONE = 0, /* Nothing special (none of the below) */
-    BS_STOP = 1, /* We want to stop translation for any reason */
-    BS_BRANCH = 2, /* A branch condition is reached */
-    BS_EXCP = 3, /* An exception condition is reached */
-};
-
-uint32_t get_opcode(uint8_t const *code, unsigned bitBase, unsigned bitSize);
-
-typedef struct DisasContext DisasContext;
-typedef struct InstInfo InstInfo;
-
-typedef int (*translate_function_t)(DisasContext *ctx, uint32_t opcode);
-struct InstInfo {
-    target_long cpc;
-    target_long npc;
-    uint32_t opcode;
-    translate_function_t translate;
-    unsigned length;
-};
-
-/* This is the state at translation time. */
-struct DisasContext {
-    struct TranslationBlock *tb;
-    CPUAVRState *env;
-
-    InstInfo inst[2];/* two consecutive instructions */
-
-    /* Routine used to access memory */
-    int memidx;
-    int bstate;
-    int singlestep;
-};
-
-void avr_decode(uint32_t pc, uint32_t *length, uint32_t opcode,
-                        translate_function_t *translate);
-
-static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
-{
-    TranslationBlock *tb = ctx->tb;
-
-    if (ctx->singlestep == 0) {
-        tcg_gen_goto_tb(n);
-        tcg_gen_movi_i32(cpu_pc, dest);
-        tcg_gen_exit_tb((uintptr_t)tb + n);
-    } else {
-        tcg_gen_movi_i32(cpu_pc, dest);
-        gen_helper_debug(cpu_env);
-        tcg_gen_exit_tb(0);
-    }
-}
-
-#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 12/13] target-avr: Respect .inc.c convention
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (10 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 11/13] target-avr: Put all translation code into one compilation unit Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 13/13] target-avr: Merge translate-inst.inc.c into translate.c Richard Henderson
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/{decode.c => decode.inc.c}                 | 0
 target-avr/{translate-inst.c => translate-inst.inc.c} | 0
 target-avr/translate.c                                | 4 ++--
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename target-avr/{decode.c => decode.inc.c} (100%)
 rename target-avr/{translate-inst.c => translate-inst.inc.c} (100%)

diff --git a/target-avr/decode.c b/target-avr/decode.inc.c
similarity index 100%
rename from target-avr/decode.c
rename to target-avr/decode.inc.c
diff --git a/target-avr/translate-inst.c b/target-avr/translate-inst.inc.c
similarity index 100%
rename from target-avr/translate-inst.c
rename to target-avr/translate-inst.inc.c
diff --git a/target-avr/translate.c b/target-avr/translate.c
index cb99b49..657e034 100644
--- a/target-avr/translate.c
+++ b/target-avr/translate.c
@@ -105,8 +105,8 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 
 #include "exec/gen-icount.h"
 #include "translate-inst.h"
-#include "translate-inst.c"
-#include "decode.c"
+#include "translate-inst.inc.c"
+#include "decode.inc.c"
 
 void avr_translate_init(void)
 {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH v18 13/13] target-avr: Merge translate-inst.inc.c into translate.c
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (11 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 12/13] target-avr: Respect .inc.c convention Richard Henderson
@ 2016-09-16 22:00 ` Richard Henderson
  2016-09-16 22:34 ` [Qemu-devel] [PATCH v18 00/13] AVR target no-reply
  2016-09-17 19:55 ` Michael Rolnik
  14 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2016-09-16 22:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mrolnik

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-avr/translate-inst.inc.c | 2602 ---------------------------------------
 target-avr/translate.c          | 2585 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 2584 insertions(+), 2603 deletions(-)
 delete mode 100644 target-avr/translate-inst.inc.c

diff --git a/target-avr/translate-inst.inc.c b/target-avr/translate-inst.inc.c
deleted file mode 100644
index 827ec7b..0000000
--- a/target-avr/translate-inst.inc.c
+++ /dev/null
@@ -1,2602 +0,0 @@
-/*
- *  QEMU AVR CPU
- *
- *  Copyright (c) 2016 Michael Rolnik
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, see
- *  <http://www.gnu.org/licenses/lgpl-2.1.html>
- */
-
-static void gen_add_CHf(TCGv R, TCGv Rd, TCGv Rr)
-{
-    TCGv t1 = tcg_temp_new_i32();
-    TCGv t2 = tcg_temp_new_i32();
-    TCGv t3 = tcg_temp_new_i32();
-
-    tcg_gen_and_tl(t1, Rd, Rr); /* t1 = Rd & Rr */
-    tcg_gen_andc_tl(t2, Rd, R); /* t2 = Rd & ~R */
-    tcg_gen_andc_tl(t3, Rr, R); /* t3 = Rr & ~R */
-    tcg_gen_or_tl(t1, t1, t2); /* t1 = t1 | t2 | t3 */
-    tcg_gen_or_tl(t1, t1, t3);
-
-    tcg_gen_shri_tl(cpu_Cf, t1, 7); /* Cf = t1(7) */
-    tcg_gen_shri_tl(cpu_Hf, t1, 3); /* Hf = t1(3) */
-    tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
-
-    tcg_temp_free_i32(t3);
-    tcg_temp_free_i32(t2);
-    tcg_temp_free_i32(t1);
-}
-
-static void gen_add_Vf(TCGv R, TCGv Rd, TCGv Rr)
-{
-    TCGv t1 = tcg_temp_new_i32();
-    TCGv t2 = tcg_temp_new_i32();
-
-        /* t1 = Rd & Rr & ~R | ~Rd & ~Rr & R = (Rd ^ R) & ~(Rd ^ Rr) */
-    tcg_gen_xor_tl(t1, Rd, R);
-    tcg_gen_xor_tl(t2, Rd, Rr);
-    tcg_gen_andc_tl(t1, t1, t2);
-
-    tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
-
-    tcg_temp_free_i32(t2);
-    tcg_temp_free_i32(t1);
-}
-
-static void gen_sub_CHf(TCGv R, TCGv Rd, TCGv Rr)
-{
-    TCGv t1 = tcg_temp_new_i32();
-    TCGv t2 = tcg_temp_new_i32();
-    TCGv t3 = tcg_temp_new_i32();
-
-    /* Cf & Hf */
-    tcg_gen_not_tl(t1, Rd); /* t1 = ~Rd */
-    tcg_gen_and_tl(t2, t1, Rr); /* t2 = ~Rd & Rr */
-    tcg_gen_or_tl(t3, t1, Rr); /* t3 = (~Rd | Rr) & R */
-    tcg_gen_and_tl(t3, t3, R);
-    tcg_gen_or_tl(t2, t2, t3); /* t2 = ~Rd & Rr | ~Rd & R | R & Rr */
-    tcg_gen_shri_tl(cpu_Cf, t2, 7); /* Cf = t2(7) */
-    tcg_gen_shri_tl(cpu_Hf, t2, 3); /* Hf = t2(3) */
-    tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
-
-    tcg_temp_free_i32(t3);
-    tcg_temp_free_i32(t2);
-    tcg_temp_free_i32(t1);
-}
-
-static void gen_sub_Vf(TCGv R, TCGv Rd, TCGv Rr)
-{
-    TCGv t1 = tcg_temp_new_i32();
-    TCGv t2 = tcg_temp_new_i32();
-
-    /* Vf */
-        /* t1 = Rd & ~Rr & ~R | ~Rd & Rr & R = (Rd ^ R) & (Rd ^ R) */
-    tcg_gen_xor_tl(t1, Rd, R);
-    tcg_gen_xor_tl(t2, Rd, Rr);
-    tcg_gen_and_tl(t1, t1, t2);
-    tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
-
-    tcg_temp_free_i32(t2);
-    tcg_temp_free_i32(t1);
-}
-
-static void gen_NSf(TCGv R)
-{
-    tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
-    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
-}
-
-static void gen_ZNSf(TCGv R)
-{
-    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
-    tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
-    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
-}
-
-static void gen_push_ret(DisasContext *ctx, int ret)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
-
-        TCGv t0 = tcg_const_i32((ret & 0x0000ff));
-
-        tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_UB);
-        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
-
-        tcg_temp_free_i32(t0);
-    } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
-
-        TCGv t0 = tcg_const_i32((ret & 0x00ffff));
-
-        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
-        tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_BEUW);
-        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
-
-        tcg_temp_free_i32(t0);
-
-    } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
-
-        TCGv lo = tcg_const_i32((ret & 0x0000ff));
-        TCGv hi = tcg_const_i32((ret & 0xffff00) >> 8);
-
-        tcg_gen_qemu_st_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
-        tcg_gen_subi_tl(cpu_sp, cpu_sp, 2);
-        tcg_gen_qemu_st_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
-        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
-
-        tcg_temp_free_i32(lo);
-        tcg_temp_free_i32(hi);
-    }
-}
-
-static void gen_pop_ret(DisasContext *ctx, TCGv ret)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
-
-        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
-        tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_UB);
-
-    } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
-
-        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
-        tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_BEUW);
-        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
-
-    } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
-
-        TCGv lo = tcg_temp_new_i32();
-        TCGv hi = tcg_temp_new_i32();
-
-        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
-        tcg_gen_qemu_ld_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
-
-        tcg_gen_addi_tl(cpu_sp, cpu_sp, 2);
-        tcg_gen_qemu_ld_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
-
-        tcg_gen_deposit_tl(ret, lo, hi, 8, 16);
-
-        tcg_temp_free_i32(lo);
-        tcg_temp_free_i32(hi);
-    }
-}
-
-static void gen_jmp_ez(void)
-{
-    tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
-    tcg_gen_or_tl(cpu_pc, cpu_pc, cpu_eind);
-    tcg_gen_exit_tb(0);
-}
-
-static void gen_jmp_z(void)
-{
-    tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
-    tcg_gen_exit_tb(0);
-}
-
-/*
- *  in the gen_set_addr & gen_get_addr functions
- *  H assumed to be in 0x00ff0000 format
- *  M assumed to be in 0x000000ff format
- *  L assumed to be in 0x000000ff format
- */
-static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L)
-{
-
-    tcg_gen_andi_tl(L, addr, 0x000000ff);
-
-    tcg_gen_andi_tl(M, addr, 0x0000ff00);
-    tcg_gen_shri_tl(M, M, 8);
-
-    tcg_gen_andi_tl(H, addr, 0x00ff0000);
-}
-
-static void gen_set_xaddr(TCGv addr)
-{
-    gen_set_addr(addr, cpu_rampX, cpu_r[27], cpu_r[26]);
-}
-
-static void gen_set_yaddr(TCGv addr)
-{
-    gen_set_addr(addr, cpu_rampY, cpu_r[29], cpu_r[28]);
-}
-
-static void gen_set_zaddr(TCGv addr)
-{
-    gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]);
-}
-
-static TCGv gen_get_addr(TCGv H, TCGv M, TCGv L)
-{
-    TCGv addr = tcg_temp_new_i32();
-
-    tcg_gen_deposit_tl(addr, M, H, 8, 8);
-    tcg_gen_deposit_tl(addr, L, addr, 8, 16);
-
-    return addr;
-}
-
-static TCGv gen_get_xaddr(void)
-{
-    return gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]);
-}
-
-static TCGv gen_get_yaddr(void)
-{
-    return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
-}
-
-static TCGv gen_get_zaddr(void)
-{
-    return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
-}
-
-/*
- *  Adds two registers and the contents of the C Flag and places the result in
- *  the destination register Rd.
- */
-static int avr_translate_ADC(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[ADC_Rd(opcode)];
-    TCGv Rr = cpu_r[ADC_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_add_tl(R, Rd, Rr); /* R = Rd + Rr + Cf */
-    tcg_gen_add_tl(R, R, cpu_Cf);
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_add_CHf(R, Rd, Rr);
-    gen_add_Vf(R, Rd, Rr);
-    gen_ZNSf(R);
-
-    /* R */
-    tcg_gen_mov_tl(Rd, R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  Adds two registers without the C Flag and places the result in the
- *  destination register Rd.
- */
-static int avr_translate_ADD(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[ADD_Rd(opcode)];
-    TCGv Rr = cpu_r[ADD_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_add_tl(R, Rd, Rr); /* Rd = Rd + Rr */
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_add_CHf(R, Rd, Rr);
-    gen_add_Vf(R, Rd, Rr);
-    gen_ZNSf(R);
-
-    /* R */
-    tcg_gen_mov_tl(Rd, R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  Adds an immediate value (0 - 63) to a register pair and places the result
- *  in the register pair. This instruction operates on the upper four register
- *  pairs, and is well suited for operations on the pointer registers.  This
- *  instruction is not available in all devices. Refer to the device specific
- *  instruction set summary.
- */
-static int avr_translate_ADIW(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv RdL = cpu_r[24 + 2 * ADIW_Rd(opcode)];
-    TCGv RdH = cpu_r[25 + 2 * ADIW_Rd(opcode)];
-    int Imm = (ADIW_Imm(opcode));
-    TCGv R = tcg_temp_new_i32();
-    TCGv Rd = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
-    tcg_gen_addi_tl(R, Rd, Imm); /* R = Rd + Imm */
-    tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
-
-    /* Cf */
-    tcg_gen_andc_tl(cpu_Cf, Rd, R); /* Cf = Rd & ~R */
-    tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15);
-
-    /* Vf */
-    tcg_gen_andc_tl(cpu_Vf, R, Rd); /* Vf = R & ~Rd */
-    tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15);
-
-    /* Zf */
-    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
-
-    /* Nf */
-    tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
-
-    /* Sf */
-    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);/* Sf = Nf ^ Vf */
-
-    /* R */
-    tcg_gen_andi_tl(RdL, R, 0xff);
-    tcg_gen_shri_tl(RdH, R, 8);
-
-    tcg_temp_free_i32(Rd);
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  Performs the logical AND between the contents of register Rd and register
- *  Rr and places the result in the destination register Rd.
- */
-static int avr_translate_AND(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[AND_Rd(opcode)];
-    TCGv Rr = cpu_r[AND_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_and_tl(R, Rd, Rr); /* Rd = Rd and Rr */
-
-    /* Vf */
-    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
-
-    /* Zf */
-    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
-
-    gen_ZNSf(R);
-
-    /* R */
-    tcg_gen_mov_tl(Rd, R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  Performs the logical AND between the contents of register Rd and a constant
- *  and places the result in the destination register Rd.
- */
-static int avr_translate_ANDI(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[16 + ANDI_Rd(opcode)];
-    int Imm = (ANDI_Imm(opcode));
-
-    /* op */
-    tcg_gen_andi_tl(Rd, Rd, Imm); /* Rd = Rd & Imm */
-
-    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
-    gen_ZNSf(Rd);
-
-    return BS_NONE;
-}
-
-/*
- *  Shifts all bits in Rd one place to the right. Bit 7 is held constant. Bit 0
- *  is loaded into the C Flag of the SREG. This operation effectively divides a
- *  signed value by two without changing its sign. The Carry Flag can be used to
- *  round the result.
- */
-static int avr_translate_ASR(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[ASR_Rd(opcode)];
-    TCGv t1 = tcg_temp_new_i32();
-    TCGv t2 = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_andi_tl(t1, Rd, 0x80); /* t1 = (Rd & 0x80) | (Rd >> 1) */
-    tcg_gen_shri_tl(t2, Rd, 1);
-    tcg_gen_or_tl(t1, t1, t2);
-
-    /* Cf */
-    tcg_gen_andi_tl(cpu_Cf, Rd, 1); /* Cf = Rd(0) */
-
-    /* Vf */
-    tcg_gen_and_tl(cpu_Vf, cpu_Nf, cpu_Cf);/* Vf = Nf & Cf */
-
-    gen_ZNSf(t1);
-
-    /* op */
-    tcg_gen_mov_tl(Rd, t1);
-
-    tcg_temp_free_i32(t2);
-    tcg_temp_free_i32(t1);
-
-    return BS_NONE;
-}
-
-/*
- *  Clears a single Flag in SREG.
- */
-static int avr_translate_BCLR(DisasContext *ctx, uint32_t opcode)
-{
-    switch (BCLR_Bit(opcode)) {
-    case 0x00:
-        tcg_gen_movi_tl(cpu_Cf, 0x00);
-        break;
-    case 0x01:
-        tcg_gen_movi_tl(cpu_Zf, 0x01);
-        break;
-    case 0x02:
-        tcg_gen_movi_tl(cpu_Nf, 0x00);
-        break;
-    case 0x03:
-        tcg_gen_movi_tl(cpu_Vf, 0x00);
-        break;
-    case 0x04:
-        tcg_gen_movi_tl(cpu_Sf, 0x00);
-        break;
-    case 0x05:
-        tcg_gen_movi_tl(cpu_Hf, 0x00);
-        break;
-    case 0x06:
-        tcg_gen_movi_tl(cpu_Tf, 0x00);
-        break;
-    case 0x07:
-        tcg_gen_movi_tl(cpu_If, 0x00);
-        break;
-    }
-
-    return BS_NONE;
-}
-
-/*
- *  Copies the T Flag in the SREG (Status Register) to bit b in register Rd.
- */
-static int avr_translate_BLD(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[BLD_Rd(opcode)];
-    TCGv t1 = tcg_temp_new_i32();
-
-    tcg_gen_andi_tl(Rd, Rd, ~(1u << BLD_Bit(opcode))); /* clear bit */
-    tcg_gen_shli_tl(t1, cpu_Tf, BLD_Bit(opcode)); /* create mask */
-    tcg_gen_or_tl(Rd, Rd, t1);
-
-    tcg_temp_free_i32(t1);
-
-    return BS_NONE;
-}
-
-/*
- *  Conditional relative branch. Tests a single bit in SREG and branches
- *  relatively to PC if the bit is cleared. This instruction branches relatively
- *  to PC in either direction (PC - 63 < = destination <= PC + 64). The
- *  parameter k is the offset from PC and is represented in two's complement
- *  form.
- */
-static int avr_translate_BRBC(DisasContext *ctx, uint32_t opcode)
-{
-    TCGLabel *taken = gen_new_label();
-    int Imm = sextract32(BRBC_Imm(opcode), 0, 7);
-
-    switch (BRBC_Bit(opcode)) {
-    case 0x00:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Cf, 0, taken);
-        break;
-    case 0x01:
-        tcg_gen_brcondi_i32(TCG_COND_NE, cpu_Zf, 0, taken);
-        break;
-    case 0x02:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Nf, 0, taken);
-        break;
-    case 0x03:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Vf, 0, taken);
-        break;
-    case 0x04:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Sf, 0, taken);
-        break;
-    case 0x05:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Hf, 0, taken);
-        break;
-    case 0x06:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Tf, 0, taken);
-        break;
-    case 0x07:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_If, 0, taken);
-        break;
-    }
-
-    gen_goto_tb(ctx, 1, ctx->inst[0].npc);
-    gen_set_label(taken);
-    gen_goto_tb(ctx, 0, ctx->inst[0].npc + Imm);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Conditional relative branch. Tests a single bit in SREG and branches
- *  relatively to PC if the bit is set. This instruction branches relatively to
- *  PC in either direction (PC - 63 < = destination <= PC + 64). The parameter k
- *  is the offset from PC and is represented in two's complement form.
- */
-static int avr_translate_BRBS(DisasContext *ctx, uint32_t opcode)
-{
-    TCGLabel *taken = gen_new_label();
-    int Imm = sextract32(BRBS_Imm(opcode), 0, 7);
-
-    switch (BRBS_Bit(opcode)) {
-    case 0x00:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Cf, 1, taken);
-        break;
-    case 0x01:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Zf, 0, taken);
-        break;
-    case 0x02:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Nf, 1, taken);
-        break;
-    case 0x03:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Vf, 1, taken);
-        break;
-    case 0x04:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Sf, 1, taken);
-        break;
-    case 0x05:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Hf, 1, taken);
-        break;
-    case 0x06:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Tf, 1, taken);
-        break;
-    case 0x07:
-        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_If, 1, taken);
-        break;
-    }
-
-    gen_goto_tb(ctx, 1, ctx->inst[0].npc);
-    gen_set_label(taken);
-    gen_goto_tb(ctx, 0, ctx->inst[0].npc + Imm);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Sets a single Flag or bit in SREG.
- */
-static int avr_translate_BSET(DisasContext *ctx, uint32_t opcode)
-{
-    switch (BSET_Bit(opcode)) {
-    case 0x00:
-        tcg_gen_movi_tl(cpu_Cf, 0x01);
-        break;
-    case 0x01:
-        tcg_gen_movi_tl(cpu_Zf, 0x00);
-        break;
-    case 0x02:
-        tcg_gen_movi_tl(cpu_Nf, 0x01);
-        break;
-    case 0x03:
-        tcg_gen_movi_tl(cpu_Vf, 0x01);
-        break;
-    case 0x04:
-        tcg_gen_movi_tl(cpu_Sf, 0x01);
-        break;
-    case 0x05:
-        tcg_gen_movi_tl(cpu_Hf, 0x01);
-        break;
-    case 0x06:
-        tcg_gen_movi_tl(cpu_Tf, 0x01);
-        break;
-    case 0x07:
-        tcg_gen_movi_tl(cpu_If, 0x01);
-        break;
-    }
-
-    return BS_NONE;
-}
-
-/*
- *  The BREAK instruction is used by the On-chip Debug system, and is
- *  normally not used in the application software. When the BREAK instruction is
- *  executed, the AVR CPU is set in the Stopped Mode. This gives the On-chip
- *  Debugger access to internal resources.  If any Lock bits are set, or either
- *  the JTAGEN or OCDEN Fuses are unprogrammed, the CPU will treat the BREAK
- *  instruction as a NOP and will not enter the Stopped mode.  This instruction
- *  is not available in all devices. Refer to the device specific instruction
- *  set summary.
- */
-static int avr_translate_BREAK(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_BREAK) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    /* TODO:   ??? */
-    return BS_NONE;
-}
-
-/*
- *  Stores bit b from Rd to the T Flag in SREG (Status Register).
- */
-static int avr_translate_BST(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[BST_Rd(opcode)];
-
-    tcg_gen_andi_tl(cpu_Tf, Rd, 1 << BST_Bit(opcode));
-    tcg_gen_shri_tl(cpu_Tf, cpu_Tf, BST_Bit(opcode));
-
-    return BS_NONE;
-}
-
-/*
- *  Calls to a subroutine within the entire Program memory. The return
- *  address (to the instruction after the CALL) will be stored onto the Stack.
- *  (See also RCALL). The Stack Pointer uses a post-decrement scheme during
- *  CALL.  This instruction is not available in all devices. Refer to the device
- *  specific instruction set summary.
- */
-static int avr_translate_CALL(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_JMP_CALL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    int Imm = CALL_Imm(opcode);
-    int ret = ctx->inst[0].npc;
-
-    gen_push_ret(ctx, ret);
-    gen_goto_tb(ctx, 0, Imm);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Clears a specified bit in an I/O Register. This instruction operates on
- *  the lower 32 I/O Registers -- addresses 0-31.
- */
-static int avr_translate_CBI(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv data = tcg_temp_new_i32();
-    TCGv port = tcg_const_i32(CBI_Imm(opcode));
-
-    gen_helper_inb(data, cpu_env, port);
-    tcg_gen_andi_tl(data, data, ~(1 << CBI_Bit(opcode)));
-    gen_helper_outb(cpu_env, port, data);
-
-    tcg_temp_free_i32(data);
-    tcg_temp_free_i32(port);
-
-    return BS_NONE;
-}
-
-/*
- *  Clears the specified bits in register Rd. Performs the logical AND
- *  between the contents of register Rd and the complement of the constant mask
- *  K. The result will be placed in register Rd.
- */
-static int avr_translate_COM(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[COM_Rd(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    tcg_gen_xori_tl(Rd, Rd, 0xff);
-
-    tcg_gen_movi_tl(cpu_Cf, 1); /* Cf = 1 */
-    tcg_gen_movi_tl(cpu_Vf, 0); /* Vf = 0 */
-    gen_ZNSf(Rd);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs a compare between two registers Rd and Rr.
- *  None of the registers are changed. All conditional branches can be used
- *  after this instruction.
- */
-static int avr_translate_CP(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[CP_Rd(opcode)];
-    TCGv Rr = cpu_r[CP_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_sub_CHf(R, Rd, Rr);
-    gen_sub_Vf(R, Rd, Rr);
-    gen_ZNSf(R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs a compare between two registers Rd and Rr and
- *  also takes into account the previous carry. None of the registers are
- *  changed. All conditional branches can be used after this instruction.
- */
-static int avr_translate_CPC(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[CPC_Rd(opcode)];
-    TCGv Rr = cpu_r[CPC_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
-    tcg_gen_sub_tl(R, R, cpu_Cf);
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_sub_CHf(R, Rd, Rr);
-    gen_sub_Vf(R, Rd, Rr);
-    gen_NSf(R);
-
-    /* Previous value remains unchanged when the result is zero;
-     * cleared otherwise.
-     */
-    tcg_gen_or_tl(cpu_Zf, cpu_Zf, R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs a compare between register Rd and a constant.
- *  The register is not changed. All conditional branches can be used after this
- *  instruction.
- */
-static int avr_translate_CPI(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[16 + CPI_Rd(opcode)];
-    int Imm = CPI_Imm(opcode);
-    TCGv Rr = tcg_const_i32(Imm);
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_sub_CHf(R, Rd, Rr);
-    gen_sub_Vf(R, Rd, Rr);
-    gen_ZNSf(R);
-
-    tcg_temp_free_i32(R);
-    tcg_temp_free_i32(Rr);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs a compare between two registers Rd and Rr, and
- *  skips the next instruction if Rd = Rr.
- */
-static int avr_translate_CPSE(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[CPSE_Rd(opcode)];
-    TCGv Rr = cpu_r[CPSE_Rr(opcode)];
-    TCGLabel *skip = gen_new_label();
-
-        /* PC if next inst is skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
-    tcg_gen_brcond_i32(TCG_COND_EQ, Rd, Rr, skip);
-        /* PC if next inst is not skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
-    gen_set_label(skip);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Subtracts one -1- from the contents of register Rd and places the result
- *  in the destination register Rd.  The C Flag in SREG is not affected by the
- *  operation, thus allowing the DEC instruction to be used on a loop counter in
- *  multiple-precision computations.  When operating on unsigned values, only
- *  BREQ and BRNE branches can be expected to perform consistently.  When
- *  operating on two's complement values, all signed branches are available.
- */
-static int avr_translate_DEC(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[DEC_Rd(opcode)];
-
-    tcg_gen_subi_tl(Rd, Rd, 1); /* Rd = Rd - 1 */
-    tcg_gen_andi_tl(Rd, Rd, 0xff); /* make it 8 bits */
-
-        /* cpu_Vf = Rd == 0x7f */
-    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x7f);
-    gen_ZNSf(Rd);
-
-    return BS_NONE;
-}
-
-/*
- *  The module is an instruction set extension to the AVR CPU, performing
- *  DES iterations. The 64-bit data block (plaintext or ciphertext) is placed in
- *  the CPU register file, registers R0-R7, where LSB of data is placed in LSB
- *  of R0 and MSB of data is placed in MSB of R7. The full 64-bit key (including
- *  parity bits) is placed in registers R8- R15, organized in the register file
- *  with LSB of key in LSB of R8 and MSB of key in MSB of R15. Executing one DES
- *  instruction performs one round in the DES algorithm. Sixteen rounds must be
- *  executed in increasing order to form the correct DES ciphertext or
- *  plaintext. Intermediate results are stored in the register file (R0-R15)
- *  after each DES instruction. The instruction's operand (K) determines which
- *  round is executed, and the half carry flag (H) determines whether encryption
- *  or decryption is performed.  The DES algorithm is described in
- *  "Specifications for the Data Encryption Standard" (Federal Information
- *  Processing Standards Publication 46). Intermediate results in this
- *  implementation differ from the standard because the initial permutation and
- *  the inverse initial permutation are performed each iteration. This does not
- *  affect the result in the final ciphertext or plaintext, but reduces
- *  execution time.
- */
-static int avr_translate_DES(DisasContext *ctx, uint32_t opcode)
-{
-    /* TODO: */
-    if (avr_feature(ctx->env, AVR_FEATURE_DES) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    return BS_NONE;
-}
-
-/*
- *  Indirect call of a subroutine pointed to by the Z (16 bits) Pointer
- *  Register in the Register File and the EIND Register in the I/O space. This
- *  instruction allows for indirect calls to the entire 4M (words) Program
- *  memory space. See also ICALL. The Stack Pointer uses a post-decrement scheme
- *  during EICALL.  This instruction is not available in all devices. Refer to
- *  the device specific instruction set summary.
- */
-static int avr_translate_EICALL(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_EIJMP_EICALL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    int ret = ctx->inst[0].npc;
-
-    gen_push_ret(ctx, ret);
-
-    gen_jmp_ez();
-
-    return BS_BRANCH;
-}
-
-/*
- *  Indirect jump to the address pointed to by the Z (16 bits) Pointer
- *  Register in the Register File and the EIND Register in the I/O space. This
- *  instruction allows for indirect jumps to the entire 4M (words) Program
- *  memory space. See also IJMP.  This instruction is not available in all
- *  devices. Refer to the device specific instruction set summary.
- */
-static int avr_translate_EIJMP(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_EIJMP_EICALL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    gen_jmp_ez();
-
-    return BS_BRANCH;
-}
-
-/*
- *  Loads one byte pointed to by the Z-register and the RAMPZ Register in
- *  the I/O space, and places this byte in the destination register Rd. This
- *  instruction features a 100% space effective constant initialization or
- *  constant data fetch. The Program memory is organized in 16-bit words while
- *  the Z-pointer is a byte address. Thus, the least significant bit of the
- *  Z-pointer selects either low byte (ZLSB = 0) or high byte (ZLSB = 1). This
- *  instruction can address the entire Program memory space. The Z-pointer
- *  Register can either be left unchanged by the operation, or it can be
- *  incremented. The incrementation applies to the entire 24-bit concatenation
- *  of the RAMPZ and Z-pointer Registers.  Devices with Self-Programming
- *  capability can use the ELPM instruction to read the Fuse and Lock bit value.
- *  Refer to the device documentation for a detailed description.  This
- *  instruction is not available in all devices. Refer to the device specific
- *  instruction set summary.
- */
-static int avr_translate_ELPM1(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_ELPM) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rd = cpu_r[0];
-    TCGv addr = gen_get_zaddr();
-
-    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_ELPM2(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_ELPM) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rd = cpu_r[ELPM2_Rd(opcode)];
-    TCGv addr = gen_get_zaddr();
-
-    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_ELPMX(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_ELPMX) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rd = cpu_r[ELPMX_Rd(opcode)];
-    TCGv addr = gen_get_zaddr();
-
-    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
-
-    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-
-    gen_set_zaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Performs the logical EOR between the contents of register Rd and
- *  register Rr and places the result in the destination register Rd.
- */
-static int avr_translate_EOR(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[EOR_Rd(opcode)];
-    TCGv Rr = cpu_r[EOR_Rr(opcode)];
-
-    tcg_gen_xor_tl(Rd, Rd, Rr);
-
-    tcg_gen_movi_tl(cpu_Vf, 0);
-    gen_ZNSf(Rd);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned
- *  multiplication and shifts the result one bit left.
- */
-static int avr_translate_FMUL(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv R0 = cpu_r[0];
-    TCGv R1 = cpu_r[1];
-    TCGv Rd = cpu_r[16 + FMUL_Rd(opcode)];
-    TCGv Rr = cpu_r[16 + FMUL_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
-    tcg_gen_shli_tl(R, R, 1);
-
-    tcg_gen_andi_tl(R0, R, 0xff);
-    tcg_gen_shri_tl(R, R, 8);
-    tcg_gen_andi_tl(R1, R, 0xff);
-
-    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
-    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
- *  and shifts the result one bit left.
- */
-static int avr_translate_FMULS(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv R0 = cpu_r[0];
-    TCGv R1 = cpu_r[1];
-    TCGv Rd = cpu_r[16 + FMULS_Rd(opcode)];
-    TCGv Rr = cpu_r[16 + FMULS_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-    TCGv t0 = tcg_temp_new_i32();
-    TCGv t1 = tcg_temp_new_i32();
-
-    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
-    tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
-    tcg_gen_mul_tl(R, t0, t1); /* R = Rd *Rr */
-    tcg_gen_shli_tl(R, R, 1);
-
-    tcg_gen_andi_tl(R0, R, 0xff);
-    tcg_gen_shri_tl(R, R, 8);
-    tcg_gen_andi_tl(R1, R, 0xff);
-
-    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
-    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
-
-    tcg_temp_free_i32(t1);
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
- *  and shifts the result one bit left.
- */
-static int avr_translate_FMULSU(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv R0 = cpu_r[0];
-    TCGv R1 = cpu_r[1];
-    TCGv Rd = cpu_r[16 + FMULSU_Rd(opcode)];
-    TCGv Rr = cpu_r[16 + FMULSU_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-    TCGv t0 = tcg_temp_new_i32();
-
-    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
-    tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
-    tcg_gen_shli_tl(R, R, 1);
-
-    tcg_gen_andi_tl(R0, R, 0xff);
-    tcg_gen_shri_tl(R, R, 8);
-    tcg_gen_andi_tl(R1, R, 0xff);
-
-    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
-    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
-
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  Calls to a subroutine within the entire 4M (words) Program memory. The
- *  return address (to the instruction after the CALL) will be stored onto the
- *  Stack. See also RCALL. The Stack Pointer uses a post-decrement scheme during
- *  CALL.  This instruction is not available in all devices. Refer to the device
- *  specific instruction set summary.
- */
-static int avr_translate_ICALL(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_IJMP_ICALL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    int ret = ctx->inst[0].npc;
-
-    gen_push_ret(ctx, ret);
-    gen_jmp_z();
-
-    return BS_BRANCH;
-}
-
-/*
- *  Indirect jump to the address pointed to by the Z (16 bits) Pointer
- *  Register in the Register File. The Z-pointer Register is 16 bits wide and
- *  allows jump within the lowest 64K words (128KB) section of Program memory.
- *  This instruction is not available in all devices. Refer to the device
- *  specific instruction set summary.
- */
-static int avr_translate_IJMP(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_IJMP_ICALL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    gen_jmp_z();
-
-    return BS_BRANCH;
-}
-
-/*
- *  Loads data from the I/O Space (Ports, Timers, Configuration Registers,
- *  etc.) into register Rd in the Register File.
- */
-static int avr_translate_IN(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[IN_Rd(opcode)];
-    int Imm = IN_Imm(opcode);
-    TCGv port = tcg_const_i32(Imm);
-
-    gen_helper_inb(Rd, cpu_env, port);
-
-    tcg_temp_free_i32(port);
-
-    return BS_NONE;
-}
-
-/*
- *  Adds one -1- to the contents of register Rd and places the result in the
- *  destination register Rd.  The C Flag in SREG is not affected by the
- *  operation, thus allowing the INC instruction to be used on a loop counter in
- *  multiple-precision computations.  When operating on unsigned numbers, only
- *  BREQ and BRNE branches can be expected to perform consistently. When
- *  operating on two's complement values, all signed branches are available.
- */
-static int avr_translate_INC(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[INC_Rd(opcode)];
-
-    tcg_gen_addi_tl(Rd, Rd, 1);
-    tcg_gen_andi_tl(Rd, Rd, 0xff);
-
-        /* cpu_Vf = Rd == 0x80 */
-    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x80);
-    gen_ZNSf(Rd);
-    return BS_NONE;
-}
-
-/*
- *  Jump to an address within the entire 4M (words) Program memory. See also
- *  RJMP.  This instruction is not available in all devices. Refer to the device
- *  specific instruction set summary.0
- */
-static int avr_translate_JMP(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_JMP_CALL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    gen_goto_tb(ctx, 0, JMP_Imm(opcode));
-    return BS_BRANCH;
-}
-
-/*
- *  Load one byte indirect from data space to register and stores an clear
- *  the bits in data space specified by the register. The instruction can only
- *  be used towards internal SRAM.  The data location is pointed to by the Z (16
- *  bits) Pointer Register in the Register File. Memory access is limited to the
- *  current data segment of 64KB. To access another data segment in devices with
- *  more than 64KB data space, the RAMPZ in register in the I/O area has to be
- *  changed.  The Z-pointer Register is left unchanged by the operation. This
- *  instruction is especially suited for clearing status bits stored in SRAM.
- */
-static void gen_data_store(DisasContext *ctx, TCGv data, TCGv addr)
-{
-    if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) {
-        gen_helper_fullwr(cpu_env, data, addr);
-    } else {
-        tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX); /* mem[addr] = data */
-    }
-}
-
-static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr)
-{
-    if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) {
-        gen_helper_fullrd(data, cpu_env, addr);
-    } else {
-        tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX); /* data = mem[addr] */
-    }
-}
-
-static int avr_translate_LAC(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rr = cpu_r[LAC_Rr(opcode)];
-    TCGv addr = gen_get_zaddr();
-    TCGv t0 = tcg_temp_new_i32();
-    TCGv t1 = tcg_temp_new_i32();
-
-    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
-        /* t1 = t0 & (0xff - Rr) = t0 and ~Rr */
-    tcg_gen_andc_tl(t1, t0, Rr);
-
-    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
-    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
-
-    tcg_temp_free_i32(t1);
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Load one byte indirect from data space to register and set bits in data
- *  space specified by the register. The instruction can only be used towards
- *  internal SRAM.  The data location is pointed to by the Z (16 bits) Pointer
- *  Register in the Register File. Memory access is limited to the current data
- *  segment of 64KB. To access another data segment in devices with more than
- *  64KB data space, the RAMPZ in register in the I/O area has to be changed.
- *  The Z-pointer Register is left unchanged by the operation. This instruction
- *  is especially suited for setting status bits stored in SRAM.
- */
-static int avr_translate_LAS(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rr = cpu_r[LAS_Rr(opcode)];
-    TCGv addr = gen_get_zaddr();
-    TCGv t0 = tcg_temp_new_i32();
-    TCGv t1 = tcg_temp_new_i32();
-
-    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
-    tcg_gen_or_tl(t1, t0, Rr);
-
-    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
-    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
-
-    tcg_temp_free_i32(t1);
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Load one byte indirect from data space to register and toggles bits in
- *  the data space specified by the register.  The instruction can only be used
- *  towards SRAM.  The data location is pointed to by the Z (16 bits) Pointer
- *  Register in the Register File. Memory access is limited to the current data
- *  segment of 64KB. To access another data segment in devices with more than
- *  64KB data space, the RAMPZ in register in the I/O area has to be changed.
- *  The Z-pointer Register is left unchanged by the operation. This instruction
- *  is especially suited for changing status bits stored in SRAM.
- */
-static int avr_translate_LAT(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rr = cpu_r[LAT_Rr(opcode)];
-    TCGv addr = gen_get_zaddr();
-    TCGv t0 = tcg_temp_new_i32();
-    TCGv t1 = tcg_temp_new_i32();
-
-    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
-    tcg_gen_xor_tl(t1, t0, Rr);
-
-    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
-    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
-
-    tcg_temp_free_i32(t1);
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Loads one byte indirect from the data space to a register. For parts
- *  with SRAM, the data space consists of the Register File, I/O memory and
- *  internal SRAM (and external SRAM if applicable). For parts without SRAM, the
- *  data space consists of the Register File only. In some parts the Flash
- *  Memory has been mapped to the data space and can be read using this command.
- *  The EEPROM has a separate address space.  The data location is pointed to by
- *  the X (16 bits) Pointer Register in the Register File. Memory access is
- *  limited to the current data segment of 64KB. To access another data segment
- *  in devices with more than 64KB data space, the RAMPX in register in the I/O
- *  area has to be changed.  The X-pointer Register can either be left unchanged
- *  by the operation, or it can be post-incremented or predecremented.  These
- *  features are especially suited for accessing arrays, tables, and Stack
- *  Pointer usage of the X-pointer Register. Note that only the low byte of the
- *  X-pointer is updated in devices with no more than 256 bytes data space. For
- *  such devices, the high byte of the pointer is not used by this instruction
- *  and can be used for other purposes. The RAMPX Register in the I/O area is
- *  updated in parts with more than 64KB data space or more than 64KB Program
- *  memory, and the increment/decrement is added to the entire 24-bit address on
- *  such devices.  Not all variants of this instruction is available in all
- *  devices. Refer to the device specific instruction set summary.  In the
- *  Reduced Core tinyAVR the LD instruction can be used to achieve the same
- *  operation as LPM since the program memory is mapped to the data memory
- *  space.
- */
-static int avr_translate_LDX1(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDX1_Rd(opcode)];
-    TCGv addr = gen_get_xaddr();
-
-    gen_data_load(ctx, Rd, addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_LDX2(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDX2_Rd(opcode)];
-    TCGv addr = gen_get_xaddr();
-
-    gen_data_load(ctx, Rd, addr);
-    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-
-    gen_set_xaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_LDX3(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDX3_Rd(opcode)];
-    TCGv addr = gen_get_xaddr();
-
-    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
-    gen_data_load(ctx, Rd, addr);
-    gen_set_xaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Loads one byte indirect with or without displacement from the data space
- *  to a register. For parts with SRAM, the data space consists of the Register
- *  File, I/O memory and internal SRAM (and external SRAM if applicable). For
- *  parts without SRAM, the data space consists of the Register File only. In
- *  some parts the Flash Memory has been mapped to the data space and can be
- *  read using this command. The EEPROM has a separate address space.  The data
- *  location is pointed to by the Y (16 bits) Pointer Register in the Register
- *  File. Memory access is limited to the current data segment of 64KB. To
- *  access another data segment in devices with more than 64KB data space, the
- *  RAMPY in register in the I/O area has to be changed.  The Y-pointer Register
- *  can either be left unchanged by the operation, or it can be post-incremented
- *  or predecremented.  These features are especially suited for accessing
- *  arrays, tables, and Stack Pointer usage of the Y-pointer Register. Note that
- *  only the low byte of the Y-pointer is updated in devices with no more than
- *  256 bytes data space. For such devices, the high byte of the pointer is not
- *  used by this instruction and can be used for other purposes. The RAMPY
- *  Register in the I/O area is updated in parts with more than 64KB data space
- *  or more than 64KB Program memory, and the increment/decrement/displacement
- *  is added to the entire 24-bit address on such devices.  Not all variants of
- *  this instruction is available in all devices. Refer to the device specific
- *  instruction set summary.  In the Reduced Core tinyAVR the LD instruction can
- *  be used to achieve the same operation as LPM since the program memory is
- *  mapped to the data memory space.
- */
-static int avr_translate_LDY2(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDY2_Rd(opcode)];
-    TCGv addr = gen_get_yaddr();
-
-    gen_data_load(ctx, Rd, addr);
-    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-
-    gen_set_yaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_LDY3(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDY3_Rd(opcode)];
-    TCGv addr = gen_get_yaddr();
-
-    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
-    gen_data_load(ctx, Rd, addr);
-    gen_set_yaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_LDDY(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDDY_Rd(opcode)];
-    TCGv addr = gen_get_yaddr();
-
-    tcg_gen_addi_tl(addr, addr, LDDY_Imm(opcode)); /* addr = addr + q */
-    gen_data_load(ctx, Rd, addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Loads one byte indirect with or without displacement from the data space
- *  to a register. For parts with SRAM, the data space consists of the Register
- *  File, I/O memory and internal SRAM (and external SRAM if applicable). For
- *  parts without SRAM, the data space consists of the Register File only. In
- *  some parts the Flash Memory has been mapped to the data space and can be
- *  read using this command. The EEPROM has a separate address space.  The data
- *  location is pointed to by the Z (16 bits) Pointer Register in the Register
- *  File. Memory access is limited to the current data segment of 64KB. To
- *  access another data segment in devices with more than 64KB data space, the
- *  RAMPZ in register in the I/O area has to be changed.  The Z-pointer Register
- *  can either be left unchanged by the operation, or it can be post-incremented
- *  or predecremented.  These features are especially suited for Stack Pointer
- *  usage of the Z-pointer Register, however because the Z-pointer Register can
- *  be used for indirect subroutine calls, indirect jumps and table lookup, it
- *  is often more convenient to use the X or Y-pointer as a dedicated Stack
- *  Pointer. Note that only the low byte of the Z-pointer is updated in devices
- *  with no more than 256 bytes data space. For such devices, the high byte of
- *  the pointer is not used by this instruction and can be used for other
- *  purposes. The RAMPZ Register in the I/O area is updated in parts with more
- *  than 64KB data space or more than 64KB Program memory, and the
- *  increment/decrement/displacement is added to the entire 24-bit address on
- *  such devices.  Not all variants of this instruction is available in all
- *  devices. Refer to the device specific instruction set summary.  In the
- *  Reduced Core tinyAVR the LD instruction can be used to achieve the same
- *  operation as LPM since the program memory is mapped to the data memory
- *  space.  For using the Z-pointer for table lookup in Program memory see the
- *  LPM and ELPM instructions.
- */
-static int avr_translate_LDZ2(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDZ2_Rd(opcode)];
-    TCGv addr = gen_get_zaddr();
-
-    gen_data_load(ctx, Rd, addr);
-    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-
-    gen_set_zaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_LDZ3(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDZ3_Rd(opcode)];
-    TCGv addr = gen_get_zaddr();
-
-    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
-    gen_data_load(ctx, Rd, addr);
-
-    gen_set_zaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_LDDZ(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDDZ_Rd(opcode)];
-    TCGv addr = gen_get_zaddr();
-
-    tcg_gen_addi_tl(addr, addr, LDDZ_Imm(opcode));
-                                                    /* addr = addr + q */
-    gen_data_load(ctx, Rd, addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
-    Loads an 8 bit constant directly to register 16 to 31.
- */
-static int avr_translate_LDI(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[16 + LDI_Rd(opcode)];
-    int imm = LDI_Imm(opcode);
-
-    tcg_gen_movi_tl(Rd, imm);
-
-    return BS_NONE;
-}
-
-/*
- *  Loads one byte from the data space to a register. For parts with SRAM,
- *  the data space consists of the Register File, I/O memory and internal SRAM
- *  (and external SRAM if applicable). For parts without SRAM, the data space
- *  consists of the register file only. The EEPROM has a separate address space.
- *  A 16-bit address must be supplied. Memory access is limited to the current
- *  data segment of 64KB. The LDS instruction uses the RAMPD Register to access
- *  memory above 64KB. To access another data segment in devices with more than
- *  64KB data space, the RAMPD in register in the I/O area has to be changed.
- *  This instruction is not available in all devices. Refer to the device
- *  specific instruction set summary.
- */
-static int avr_translate_LDS(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LDS_Rd(opcode)];
-    TCGv addr = tcg_temp_new_i32();
-    TCGv H = cpu_rampD;
-
-    tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
-    tcg_gen_shli_tl(addr, addr, 16);
-    tcg_gen_ori_tl(addr, addr, LDS_Imm(opcode));
-
-    gen_data_load(ctx, Rd, addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Loads one byte pointed to by the Z-register into the destination
- *  register Rd. This instruction features a 100% space effective constant
- *  initialization or constant data fetch. The Program memory is organized in
- *  16-bit words while the Z-pointer is a byte address. Thus, the least
- *  significant bit of the Z-pointer selects either low byte (ZLSB = 0) or high
- *  byte (ZLSB = 1). This instruction can address the first 64KB (32K words) of
- *  Program memory. The Zpointer Register can either be left unchanged by the
- *  operation, or it can be incremented. The incrementation does not apply to
- *  the RAMPZ Register.  Devices with Self-Programming capability can use the
- *  LPM instruction to read the Fuse and Lock bit values.  Refer to the device
- *  documentation for a detailed description.  The LPM instruction is not
- *  available in all devices. Refer to the device specific instruction set
- *  summary
- */
-static int avr_translate_LPM1(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_LPM) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rd = cpu_r[0];
-    TCGv addr = tcg_temp_new_i32();
-    TCGv H = cpu_r[31];
-    TCGv L = cpu_r[30];
-
-    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
-    tcg_gen_or_tl(addr, addr, L);
-
-    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_LPM2(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_LPM) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rd = cpu_r[LPM2_Rd(opcode)];
-    TCGv addr = tcg_temp_new_i32();
-    TCGv H = cpu_r[31];
-    TCGv L = cpu_r[30];
-
-    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
-    tcg_gen_or_tl(addr, addr, L);
-
-    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_LPMX(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_LPMX) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rd = cpu_r[LPMX_Rd(opcode)];
-    TCGv addr = tcg_temp_new_i32();
-    TCGv H = cpu_r[31];
-    TCGv L = cpu_r[30];
-
-    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
-    tcg_gen_or_tl(addr, addr, L);
-
-    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
-
-    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-
-    tcg_gen_andi_tl(L, addr, 0xff);
-
-    tcg_gen_shri_tl(addr, addr, 8);
-    tcg_gen_andi_tl(H, addr, 0xff);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Shifts all bits in Rd one place to the right. Bit 7 is cleared. Bit 0 is
- *  loaded into the C Flag of the SREG. This operation effectively divides an
- *  unsigned value by two. The C Flag can be used to round the result.
- */
-static int avr_translate_LSR(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[LSR_Rd(opcode)];
-
-    tcg_gen_andi_tl(cpu_Cf, Rd, 1);
-
-    tcg_gen_shri_tl(Rd, Rd, 1);
-
-    gen_ZNSf(Rd);
-    tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
-    return BS_NONE;
-}
-
-/*
- *  This instruction makes a copy of one register into another. The source
- *  register Rr is left unchanged, while the destination register Rd is loaded
- *  with a copy of Rr.
- */
-static int avr_translate_MOV(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[MOV_Rd(opcode)];
-    TCGv Rr = cpu_r[MOV_Rr(opcode)];
-
-    tcg_gen_mov_tl(Rd, Rr);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction makes a copy of one register pair into another register
- *  pair. The source register pair Rr+1:Rr is left unchanged, while the
- *  destination register pair Rd+1:Rd is loaded with a copy of Rr + 1:Rr.  This
- *  instruction is not available in all devices. Refer to the device specific
- *  instruction set summary.
- */
-static int avr_translate_MOVW(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_MOVW) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv RdL = cpu_r[MOVW_Rd(opcode) * 2 + 0];
-    TCGv RdH = cpu_r[MOVW_Rd(opcode) * 2 + 1];
-    TCGv RrL = cpu_r[MOVW_Rr(opcode) * 2 + 0];
-    TCGv RrH = cpu_r[MOVW_Rr(opcode) * 2 + 1];
-
-    tcg_gen_mov_tl(RdH, RrH);
-    tcg_gen_mov_tl(RdL, RrL);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication.
- */
-static int avr_translate_MUL(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv R0 = cpu_r[0];
-    TCGv R1 = cpu_r[1];
-    TCGv Rd = cpu_r[MUL_Rd(opcode)];
-    TCGv Rr = cpu_r[MUL_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
-
-    tcg_gen_mov_tl(R0, R);
-    tcg_gen_andi_tl(R0, R0, 0xff);
-    tcg_gen_shri_tl(R, R, 8);
-    tcg_gen_mov_tl(R1, R);
-
-    tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
-    tcg_gen_mov_tl(cpu_Zf, R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication.
- */
-static int avr_translate_MULS(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv R0 = cpu_r[0];
-    TCGv R1 = cpu_r[1];
-    TCGv Rd = cpu_r[16 + MULS_Rd(opcode)];
-    TCGv Rr = cpu_r[16 + MULS_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-    TCGv t0 = tcg_temp_new_i32();
-    TCGv t1 = tcg_temp_new_i32();
-
-    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
-    tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
-    tcg_gen_mul_tl(R, t0, t1); /* R = Rd * Rr */
-
-    tcg_gen_mov_tl(R0, R);
-    tcg_gen_andi_tl(R0, R0, 0xff);
-    tcg_gen_shri_tl(R, R, 8);
-    tcg_gen_mov_tl(R1, R);
-    tcg_gen_andi_tl(R1, R0, 0xff);
-
-    tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
-    tcg_gen_mov_tl(cpu_Zf, R);
-
-    tcg_temp_free_i32(t1);
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a
- *  signed and an unsigned number.
- */
-static int avr_translate_MULSU(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv R0 = cpu_r[0];
-    TCGv R1 = cpu_r[1];
-    TCGv Rd = cpu_r[16 + MULSU_Rd(opcode)];
-    TCGv Rr = cpu_r[16 + MULSU_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-    TCGv t0 = tcg_temp_new_i32();
-
-    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
-    tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
-
-    tcg_gen_mov_tl(R0, R);
-    tcg_gen_andi_tl(R0, R0, 0xff);
-    tcg_gen_shri_tl(R, R, 8);
-    tcg_gen_mov_tl(R1, R);
-    tcg_gen_andi_tl(R1, R0, 0xff);
-
-    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
-    tcg_gen_mov_tl(cpu_Zf, R);
-
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  Replaces the contents of register Rd with its two's complement; the
- *  value $80 is left unchanged.
- */
-static int avr_translate_NEG(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[SUB_Rd(opcode)];
-    TCGv t0 = tcg_const_i32(0);
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_sub_tl(R, t0, Rd); /* R = 0 - Rd */
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_sub_CHf(R, t0, Rd);
-    gen_sub_Vf(R, t0, Rd);
-    gen_ZNSf(R);
-
-    /* R */
-    tcg_gen_mov_tl(Rd, R);
-
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction performs a single cycle No Operation.
- */
-static int avr_translate_NOP(DisasContext *ctx, uint32_t opcode)
-{
-
-    /* NOP */
-
-    return BS_NONE;
-}
-
-/*
- *  Performs the logical OR between the contents of register Rd and register
- *  Rr and places the result in the destination register Rd.
- */
-static int avr_translate_OR(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[OR_Rd(opcode)];
-    TCGv Rr = cpu_r[OR_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    tcg_gen_or_tl(R, Rd, Rr);
-
-    tcg_gen_movi_tl(cpu_Vf, 0);
-    gen_ZNSf(R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  Performs the logical OR between the contents of register Rd and a
- *  constant and places the result in the destination register Rd.
- */
-static int avr_translate_ORI(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[16 + ORI_Rd(opcode)];
-    int Imm = (ORI_Imm(opcode));
-
-    tcg_gen_ori_tl(Rd, Rd, Imm); /* Rd = Rd | Imm */
-
-    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
-    gen_ZNSf(Rd);
-
-    return BS_NONE;
-}
-
-/*
- *  Stores data from register Rr in the Register File to I/O Space (Ports,
- *  Timers, Configuration Registers, etc.).
- */
-static int avr_translate_OUT(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[OUT_Rd(opcode)];
-    int Imm = OUT_Imm(opcode);
-    TCGv port = tcg_const_i32(Imm);
-
-    gen_helper_outb(cpu_env, port, Rd);
-
-    tcg_temp_free_i32(port);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction loads register Rd with a byte from the STACK. The Stack
- *  Pointer is pre-incremented by 1 before the POP.  This instruction is not
- *  available in all devices. Refer to the device specific instruction set
- *  summary.
- */
-static int avr_translate_POP(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[POP_Rd(opcode)];
-
-    tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
-    gen_data_load(ctx, Rd, cpu_sp);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction stores the contents of register Rr on the STACK. The
- *  Stack Pointer is post-decremented by 1 after the PUSH.  This instruction is
- *  not available in all devices. Refer to the device specific instruction set
- *  summary.
- */
-static int avr_translate_PUSH(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[PUSH_Rd(opcode)];
-
-    gen_data_store(ctx, Rd, cpu_sp);
-    tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
-
-    return BS_NONE;
-}
-
-/*
- *  Relative call to an address within PC - 2K + 1 and PC + 2K (words). The
- *  return address (the instruction after the RCALL) is stored onto the Stack.
- *  See also CALL. For AVR microcontrollers with Program memory not exceeding 4K
- *  words (8KB) this instruction can address the entire memory from every
- *  address location. The Stack Pointer uses a post-decrement scheme during
- *  RCALL.
- */
-static int avr_translate_RCALL(DisasContext *ctx, uint32_t opcode)
-{
-    int ret = ctx->inst[0].npc;
-    int dst = ctx->inst[0].npc + sextract32(RCALL_Imm(opcode), 0, 12);
-
-    gen_push_ret(ctx, ret);
-    gen_goto_tb(ctx, 0, dst);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Returns from subroutine. The return address is loaded from the STACK.
- *  The Stack Pointer uses a preincrement scheme during RET.
- */
-static int avr_translate_RET(DisasContext *ctx, uint32_t opcode)
-{
-    gen_pop_ret(ctx, cpu_pc);
-
-    tcg_gen_exit_tb(0);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Returns from interrupt. The return address is loaded from the STACK and
- *  the Global Interrupt Flag is set.  Note that the Status Register is not
- *  automatically stored when entering an interrupt routine, and it is not
- *  restored when returning from an interrupt routine. This must be handled by
- *  the application program. The Stack Pointer uses a pre-increment scheme
- *  during RETI.
- */
-static int avr_translate_RETI(DisasContext *ctx, uint32_t opcode)
-{
-    gen_pop_ret(ctx, cpu_pc);
-
-    tcg_gen_movi_tl(cpu_If, 1);
-
-    tcg_gen_exit_tb(0);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Relative jump to an address within PC - 2K +1 and PC + 2K (words). For
- *  AVR microcontrollers with Program memory not exceeding 4K words (8KB) this
- *  instruction can address the entire memory from every address location. See
- *  also JMP.
- */
-static int avr_translate_RJMP(DisasContext *ctx, uint32_t opcode)
-{
-    int dst = ctx->inst[0].npc + sextract32(RJMP_Imm(opcode), 0, 12);
-
-    gen_goto_tb(ctx, 0, dst);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Shifts all bits in Rd one place to the right. The C Flag is shifted into
- *  bit 7 of Rd. Bit 0 is shifted into the C Flag.  This operation, combined
- *  with ASR, effectively divides multi-byte signed values by two. Combined with
- *  LSR it effectively divides multi-byte unsigned values by two. The Carry Flag
- *  can be used to round the result.
- */
-static int avr_translate_ROR(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[ROR_Rd(opcode)];
-    TCGv t0 = tcg_temp_new_i32();
-
-    tcg_gen_shli_tl(t0, cpu_Cf, 7);
-    tcg_gen_andi_tl(cpu_Cf, Rd, 0);
-    tcg_gen_shri_tl(Rd, Rd, 1);
-    tcg_gen_or_tl(Rd, Rd, t0);
-
-    gen_ZNSf(Rd);
-    tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
-
-    tcg_temp_free_i32(t0);
-
-    return BS_NONE;
-}
-
-/*
- *  Subtracts two registers and subtracts with the C Flag and places the
- *  result in the destination register Rd.
- */
-static int avr_translate_SBC(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[SBC_Rd(opcode)];
-    TCGv Rr = cpu_r[SBC_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
-    tcg_gen_sub_tl(R, R, cpu_Cf);
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_sub_CHf(R, Rd, Rr);
-    gen_sub_Vf(R, Rd, Rr);
-    gen_ZNSf(R);
-
-    /* R */
-    tcg_gen_mov_tl(Rd, R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  SBCI -- Subtract Immediate with Carry
- */
-static int avr_translate_SBCI(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[16 + SBCI_Rd(opcode)];
-    TCGv Rr = tcg_const_i32(SBCI_Imm(opcode));
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
-    tcg_gen_sub_tl(R, R, cpu_Cf);
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_sub_CHf(R, Rd, Rr);
-    gen_sub_Vf(R, Rd, Rr);
-    gen_ZNSf(R);
-
-    /* R */
-    tcg_gen_mov_tl(Rd, R);
-
-    tcg_temp_free_i32(R);
-    tcg_temp_free_i32(Rr);
-
-    return BS_NONE;
-}
-
-/*
- *  Sets a specified bit in an I/O Register. This instruction operates on
- *  the lower 32 I/O Registers -- addresses 0-31.
- */
-static int avr_translate_SBI(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv data = tcg_temp_new_i32();
-    TCGv port = tcg_const_i32(SBI_Imm(opcode));
-
-    gen_helper_inb(data, cpu_env, port);
-    tcg_gen_ori_tl(data, data, 1 << SBI_Bit(opcode));
-    gen_helper_outb(cpu_env, port, data);
-
-    tcg_temp_free_i32(port);
-    tcg_temp_free_i32(data);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction tests a single bit in an I/O Register and skips the
- *  next instruction if the bit is cleared. This instruction operates on the
- *  lower 32 I/O Registers -- addresses 0-31.
- */
-static int avr_translate_SBIC(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv data = tcg_temp_new_i32();
-    TCGv port = tcg_const_i32(SBIC_Imm(opcode));
-    TCGLabel *skip = gen_new_label();
-
-    gen_helper_inb(data, cpu_env, port);
-
-        /* PC if next inst is skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
-    tcg_gen_andi_tl(data, data, 1 << SBIC_Bit(opcode));
-    tcg_gen_brcondi_i32(TCG_COND_EQ, data, 0, skip);
-        /* PC if next inst is not skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
-    gen_set_label(skip);
-
-    tcg_temp_free_i32(port);
-    tcg_temp_free_i32(data);
-
-    return BS_BRANCH;
-}
-
-/*
- *  This instruction tests a single bit in an I/O Register and skips the
- *  next instruction if the bit is set. This instruction operates on the lower
- *  32 I/O Registers -- addresses 0-31.
- */
-static int avr_translate_SBIS(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv data = tcg_temp_new_i32();
-    TCGv port = tcg_const_i32(SBIS_Imm(opcode));
-    TCGLabel *skip = gen_new_label();
-
-    gen_helper_inb(data, cpu_env, port);
-
-        /* PC if next inst is skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
-    tcg_gen_andi_tl(data, data, 1 << SBIS_Bit(opcode));
-    tcg_gen_brcondi_i32(TCG_COND_NE, data, 0, skip);
-        /* PC if next inst is not skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
-    gen_set_label(skip);
-
-    tcg_temp_free_i32(port);
-    tcg_temp_free_i32(data);
-
-    return BS_BRANCH;
-}
-
-/*
- *  Subtracts an immediate value (0-63) from a register pair and places the
- *  result in the register pair. This instruction operates on the upper four
- *  register pairs, and is well suited for operations on the Pointer Registers.
- *  This instruction is not available in all devices. Refer to the device
- *  specific instruction set summary.
- */
-static int avr_translate_SBIW(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv RdL = cpu_r[24 + 2 * SBIW_Rd(opcode)];
-    TCGv RdH = cpu_r[25 + 2 * SBIW_Rd(opcode)];
-    int Imm = (SBIW_Imm(opcode));
-    TCGv R = tcg_temp_new_i32();
-    TCGv Rd = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
-    tcg_gen_subi_tl(R, Rd, Imm); /* R = Rd - Imm */
-    tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
-
-    /* Cf */
-    tcg_gen_andc_tl(cpu_Cf, R, Rd);
-    tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15); /* Cf = R & ~Rd */
-
-    /* Vf */
-    tcg_gen_andc_tl(cpu_Vf, Rd, R);
-    tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15); /* Vf = Rd & ~R */
-
-    /* Zf */
-    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
-
-    /* Nf */
-    tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
-
-    /* Sf */
-    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
-
-    /* R */
-    tcg_gen_andi_tl(RdL, R, 0xff);
-    tcg_gen_shri_tl(RdH, R, 8);
-
-    tcg_temp_free_i32(Rd);
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction tests a single bit in a register and skips the next
- *  instruction if the bit is cleared.
- */
-static int avr_translate_SBRC(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rr = cpu_r[SBRC_Rr(opcode)];
-    TCGv t0 = tcg_temp_new_i32();
-    TCGLabel *skip = gen_new_label();
-
-        /* PC if next inst is skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
-    tcg_gen_andi_tl(t0, Rr, 1 << SBRC_Bit(opcode));
-    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, skip);
-        /* PC if next inst is not skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
-    gen_set_label(skip);
-
-    tcg_temp_free_i32(t0);
-
-    return BS_BRANCH;
-}
-
-/*
- *  This instruction tests a single bit in a register and skips the next
- *  instruction if the bit is set.
- */
-static int avr_translate_SBRS(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rr = cpu_r[SBRS_Rr(opcode)];
-    TCGv t0 = tcg_temp_new_i32();
-    TCGLabel *skip = gen_new_label();
-
-        /* PC if next inst is skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
-    tcg_gen_andi_tl(t0, Rr, 1 << SBRS_Bit(opcode));
-    tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, skip);
-        /* PC if next inst is not skipped */
-    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
-    gen_set_label(skip);
-
-    tcg_temp_free_i32(t0);
-
-    return BS_BRANCH;
-}
-
-/*
- *  This instruction sets the circuit in sleep mode defined by the MCU
- *  Control Register.
- */
-static int avr_translate_SLEEP(DisasContext *ctx, uint32_t opcode)
-{
-    gen_helper_sleep(cpu_env);
-
-    return BS_EXCP;
-}
-
-/*
- *  SPM can be used to erase a page in the Program memory, to write a page
- *  in the Program memory (that is already erased), and to set Boot Loader Lock
- *  bits. In some devices, the Program memory can be written one word at a time,
- *  in other devices an entire page can be programmed simultaneously after first
- *  filling a temporary page buffer. In all cases, the Program memory must be
- *  erased one page at a time. When erasing the Program memory, the RAMPZ and
- *  Z-register are used as page address. When writing the Program memory, the
- *  RAMPZ and Z-register are used as page or word address, and the R1:R0
- *  register pair is used as data(1). When setting the Boot Loader Lock bits,
- *  the R1:R0 register pair is used as data. Refer to the device documentation
- *  for detailed description of SPM usage. This instruction can address the
- *  entire Program memory.  The SPM instruction is not available in all devices.
- *  Refer to the device specific instruction set summary.  Note: 1. R1
- *  determines the instruction high byte, and R0 determines the instruction low
- *  byte.
- */
-static int avr_translate_SPM(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_SPM) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    /* TODO:   ??? */
-    return BS_NONE;
-}
-
-static int avr_translate_SPMX(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_SPMX) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    /* TODO:   ??? */
-    return BS_NONE;
-}
-
-static int avr_translate_STX1(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STX1_Rr(opcode)];
-    TCGv addr = gen_get_xaddr();
-
-    gen_data_store(ctx, Rd, addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_STX2(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STX2_Rr(opcode)];
-    TCGv addr = gen_get_xaddr();
-
-    gen_data_store(ctx, Rd, addr);
-    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-    gen_set_xaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_STX3(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STX3_Rr(opcode)];
-    TCGv addr = gen_get_xaddr();
-
-    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
-    gen_data_store(ctx, Rd, addr);
-    gen_set_xaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_STY2(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STY2_Rd(opcode)];
-    TCGv addr = gen_get_yaddr();
-
-    gen_data_store(ctx, Rd, addr);
-    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-    gen_set_yaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_STY3(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STY3_Rd(opcode)];
-    TCGv addr = gen_get_yaddr();
-
-    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
-    gen_data_store(ctx, Rd, addr);
-    gen_set_yaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_STDY(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STDY_Rd(opcode)];
-    TCGv addr = gen_get_yaddr();
-
-    tcg_gen_addi_tl(addr, addr, STDY_Imm(opcode));
-                                                /* addr = addr + q */
-    gen_data_store(ctx, Rd, addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_STZ2(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STZ2_Rd(opcode)];
-    TCGv addr = gen_get_zaddr();
-
-    gen_data_store(ctx, Rd, addr);
-    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-
-    gen_set_zaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_STZ3(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STZ3_Rd(opcode)];
-    TCGv addr = gen_get_zaddr();
-
-    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
-    gen_data_store(ctx, Rd, addr);
-
-    gen_set_zaddr(addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-static int avr_translate_STDZ(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STDZ_Rd(opcode)];
-    TCGv addr = gen_get_zaddr();
-
-    tcg_gen_addi_tl(addr, addr, STDZ_Imm(opcode));
-                                                    /* addr = addr + q */
-    gen_data_store(ctx, Rd, addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Stores one byte from a Register to the data space. For parts with SRAM,
- *  the data space consists of the Register File, I/O memory and internal SRAM
- *  (and external SRAM if applicable). For parts without SRAM, the data space
- *  consists of the Register File only. The EEPROM has a separate address space.
- *  A 16-bit address must be supplied. Memory access is limited to the current
- *  data segment of 64KB. The STS instruction uses the RAMPD Register to access
- *  memory above 64KB. To access another data segment in devices with more than
- *  64KB data space, the RAMPD in register in the I/O area has to be changed.
- *  This instruction is not available in all devices. Refer to the device
- *  specific instruction set summary.
- */
-static int avr_translate_STS(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[STS_Rd(opcode)];
-    TCGv addr = tcg_temp_new_i32();
-    TCGv H = cpu_rampD;
-
-    tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
-    tcg_gen_shli_tl(addr, addr, 16);
-    tcg_gen_ori_tl(addr, addr, STS_Imm(opcode));
-
-    gen_data_store(ctx, Rd, addr);
-
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
-
-/*
- *  Subtracts two registers and places the result in the destination
- *  register Rd.
- */
-static int avr_translate_SUB(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[SUB_Rd(opcode)];
-    TCGv Rr = cpu_r[SUB_Rr(opcode)];
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_sub_CHf(R, Rd, Rr);
-    gen_sub_Vf(R, Rd, Rr);
-    gen_ZNSf(R);
-
-    /* R */
-    tcg_gen_mov_tl(Rd, R);
-
-    tcg_temp_free_i32(R);
-
-    return BS_NONE;
-}
-
-/*
- *  Subtracts a register and a constant and places the result in the
- *  destination register Rd. This instruction is working on Register R16 to R31
- *  and is very well suited for operations on the X, Y, and Z-pointers.
- */
-static int avr_translate_SUBI(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[16 + SUBI_Rd(opcode)];
-    TCGv Rr = tcg_const_i32(SUBI_Imm(opcode));
-    TCGv R = tcg_temp_new_i32();
-
-    /* op */
-    tcg_gen_sub_tl(R, Rd, Rr);
-                                                    /* R = Rd - Imm */
-    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
-
-    gen_sub_CHf(R, Rd, Rr);
-    gen_sub_Vf(R, Rd, Rr);
-    gen_ZNSf(R);
-
-    /* R */
-    tcg_gen_mov_tl(Rd, R);
-
-    tcg_temp_free_i32(R);
-    tcg_temp_free_i32(Rr);
-
-    return BS_NONE;
-}
-
-/*
- *  Swaps high and low nibbles in a register.
- */
-static int avr_translate_SWAP(DisasContext *ctx, uint32_t opcode)
-{
-    TCGv Rd = cpu_r[SWAP_Rd(opcode)];
-    TCGv t0 = tcg_temp_new_i32();
-    TCGv t1 = tcg_temp_new_i32();
-
-    tcg_gen_andi_tl(t0, Rd, 0x0f);
-    tcg_gen_shli_tl(t0, t0, 4);
-    tcg_gen_andi_tl(t1, Rd, 0xf0);
-    tcg_gen_shri_tl(t1, t1, 4);
-    tcg_gen_or_tl(Rd, t0, t1);
-
-    tcg_temp_free_i32(t1);
-    tcg_temp_free_i32(t0);
-
-    return BS_NONE;
-}
-
-/*
- *  This instruction resets the Watchdog Timer. This instruction must be
- *  executed within a limited time given by the WD prescaler. See the Watchdog
- *  Timer hardware specification.
- */
-static int avr_translate_WDR(DisasContext *ctx, uint32_t opcode)
-{
-    gen_helper_wdr(cpu_env);
-
-    return BS_NONE;
-}
-
-/*
- *  Exchanges one byte indirect between register and data space.  The data
- *  location is pointed to by the Z (16 bits) Pointer Register in the Register
- *  File. Memory access is limited to the current data segment of 64KB. To
- *  access another data segment in devices with more than 64KB data space, the
- *  RAMPZ in register in the I/O area has to be changed.  The Z-pointer Register
- *  is left unchanged by the operation. This instruction is especially suited
- *  for writing/reading status bits stored in SRAM.
- */
-static int avr_translate_XCH(DisasContext *ctx, uint32_t opcode)
-{
-    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
-        gen_helper_unsupported(cpu_env);
-
-        return BS_EXCP;
-    }
-
-    TCGv Rd = cpu_r[XCH_Rd(opcode)];
-    TCGv t0 = tcg_temp_new_i32();
-    TCGv addr = gen_get_zaddr();
-
-    gen_data_load(ctx, t0, addr);
-    gen_data_store(ctx, Rd, addr);
-    tcg_gen_mov_tl(Rd, t0);
-
-    tcg_temp_free_i32(t0);
-    tcg_temp_free_i32(addr);
-
-    return BS_NONE;
-}
diff --git a/target-avr/translate.c b/target-avr/translate.c
index 657e034..b25f1c2 100644
--- a/target-avr/translate.c
+++ b/target-avr/translate.c
@@ -105,7 +105,2590 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 
 #include "exec/gen-icount.h"
 #include "translate-inst.h"
-#include "translate-inst.inc.c"
+
+static void gen_add_CHf(TCGv R, TCGv Rd, TCGv Rr)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv t3 = tcg_temp_new_i32();
+
+    tcg_gen_and_tl(t1, Rd, Rr); /* t1 = Rd & Rr */
+    tcg_gen_andc_tl(t2, Rd, R); /* t2 = Rd & ~R */
+    tcg_gen_andc_tl(t3, Rr, R); /* t3 = Rr & ~R */
+    tcg_gen_or_tl(t1, t1, t2); /* t1 = t1 | t2 | t3 */
+    tcg_gen_or_tl(t1, t1, t3);
+
+    tcg_gen_shri_tl(cpu_Cf, t1, 7); /* Cf = t1(7) */
+    tcg_gen_shri_tl(cpu_Hf, t1, 3); /* Hf = t1(3) */
+    tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_add_Vf(TCGv R, TCGv Rd, TCGv Rr)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+        /* t1 = Rd & Rr & ~R | ~Rd & ~Rr & R = (Rd ^ R) & ~(Rd ^ Rr) */
+    tcg_gen_xor_tl(t1, Rd, R);
+    tcg_gen_xor_tl(t2, Rd, Rr);
+    tcg_gen_andc_tl(t1, t1, t2);
+
+    tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_sub_CHf(TCGv R, TCGv Rd, TCGv Rr)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+    TCGv t3 = tcg_temp_new_i32();
+
+    /* Cf & Hf */
+    tcg_gen_not_tl(t1, Rd); /* t1 = ~Rd */
+    tcg_gen_and_tl(t2, t1, Rr); /* t2 = ~Rd & Rr */
+    tcg_gen_or_tl(t3, t1, Rr); /* t3 = (~Rd | Rr) & R */
+    tcg_gen_and_tl(t3, t3, R);
+    tcg_gen_or_tl(t2, t2, t3); /* t2 = ~Rd & Rr | ~Rd & R | R & Rr */
+    tcg_gen_shri_tl(cpu_Cf, t2, 7); /* Cf = t2(7) */
+    tcg_gen_shri_tl(cpu_Hf, t2, 3); /* Hf = t2(3) */
+    tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
+
+    tcg_temp_free_i32(t3);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_sub_Vf(TCGv R, TCGv Rd, TCGv Rr)
+{
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /* Vf */
+        /* t1 = Rd & ~Rr & ~R | ~Rd & Rr & R = (Rd ^ R) & (Rd ^ R) */
+    tcg_gen_xor_tl(t1, Rd, R);
+    tcg_gen_xor_tl(t2, Rd, Rr);
+    tcg_gen_and_tl(t1, t1, t2);
+    tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_NSf(TCGv R)
+{
+    tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
+    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+}
+
+static void gen_ZNSf(TCGv R)
+{
+    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+    tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
+    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+}
+
+static void gen_push_ret(DisasContext *ctx, int ret)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
+
+        TCGv t0 = tcg_const_i32((ret & 0x0000ff));
+
+        tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_UB);
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+        tcg_temp_free_i32(t0);
+    } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
+
+        TCGv t0 = tcg_const_i32((ret & 0x00ffff));
+
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+        tcg_temp_free_i32(t0);
+
+    } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
+
+        TCGv lo = tcg_const_i32((ret & 0x0000ff));
+        TCGv hi = tcg_const_i32((ret & 0xffff00) >> 8);
+
+        tcg_gen_qemu_st_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 2);
+        tcg_gen_qemu_st_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+        tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+        tcg_temp_free_i32(lo);
+        tcg_temp_free_i32(hi);
+    }
+}
+
+static void gen_pop_ret(DisasContext *ctx, TCGv ret)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
+
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_UB);
+
+    } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
+
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+
+    } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
+
+        TCGv lo = tcg_temp_new_i32();
+        TCGv hi = tcg_temp_new_i32();
+
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_ld_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+
+        tcg_gen_addi_tl(cpu_sp, cpu_sp, 2);
+        tcg_gen_qemu_ld_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
+
+        tcg_gen_deposit_tl(ret, lo, hi, 8, 16);
+
+        tcg_temp_free_i32(lo);
+        tcg_temp_free_i32(hi);
+    }
+}
+
+static void gen_jmp_ez(void)
+{
+    tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
+    tcg_gen_or_tl(cpu_pc, cpu_pc, cpu_eind);
+    tcg_gen_exit_tb(0);
+}
+
+static void gen_jmp_z(void)
+{
+    tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
+    tcg_gen_exit_tb(0);
+}
+
+/*
+ *  in the gen_set_addr & gen_get_addr functions
+ *  H assumed to be in 0x00ff0000 format
+ *  M assumed to be in 0x000000ff format
+ *  L assumed to be in 0x000000ff format
+ */
+static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L)
+{
+
+    tcg_gen_andi_tl(L, addr, 0x000000ff);
+
+    tcg_gen_andi_tl(M, addr, 0x0000ff00);
+    tcg_gen_shri_tl(M, M, 8);
+
+    tcg_gen_andi_tl(H, addr, 0x00ff0000);
+}
+
+static void gen_set_xaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampX, cpu_r[27], cpu_r[26]);
+}
+
+static void gen_set_yaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampY, cpu_r[29], cpu_r[28]);
+}
+
+static void gen_set_zaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]);
+}
+
+static TCGv gen_get_addr(TCGv H, TCGv M, TCGv L)
+{
+    TCGv addr = tcg_temp_new_i32();
+
+    tcg_gen_deposit_tl(addr, M, H, 8, 8);
+    tcg_gen_deposit_tl(addr, L, addr, 8, 16);
+
+    return addr;
+}
+
+static TCGv gen_get_xaddr(void)
+{
+    return gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]);
+}
+
+static TCGv gen_get_yaddr(void)
+{
+    return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
+}
+
+static TCGv gen_get_zaddr(void)
+{
+    return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
+}
+
+/*
+ *  Adds two registers and the contents of the C Flag and places the result in
+ *  the destination register Rd.
+ */
+static int avr_translate_ADC(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[ADC_Rd(opcode)];
+    TCGv Rr = cpu_r[ADC_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_add_tl(R, Rd, Rr); /* R = Rd + Rr + Cf */
+    tcg_gen_add_tl(R, R, cpu_Cf);
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_add_CHf(R, Rd, Rr);
+    gen_add_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Adds two registers without the C Flag and places the result in the
+ *  destination register Rd.
+ */
+static int avr_translate_ADD(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[ADD_Rd(opcode)];
+    TCGv Rr = cpu_r[ADD_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_add_tl(R, Rd, Rr); /* Rd = Rd + Rr */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_add_CHf(R, Rd, Rr);
+    gen_add_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Adds an immediate value (0 - 63) to a register pair and places the result
+ *  in the register pair. This instruction operates on the upper four register
+ *  pairs, and is well suited for operations on the pointer registers.  This
+ *  instruction is not available in all devices. Refer to the device specific
+ *  instruction set summary.
+ */
+static int avr_translate_ADIW(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv RdL = cpu_r[24 + 2 * ADIW_Rd(opcode)];
+    TCGv RdH = cpu_r[25 + 2 * ADIW_Rd(opcode)];
+    int Imm = (ADIW_Imm(opcode));
+    TCGv R = tcg_temp_new_i32();
+    TCGv Rd = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
+    tcg_gen_addi_tl(R, Rd, Imm); /* R = Rd + Imm */
+    tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
+
+    /* Cf */
+    tcg_gen_andc_tl(cpu_Cf, Rd, R); /* Cf = Rd & ~R */
+    tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15);
+
+    /* Vf */
+    tcg_gen_andc_tl(cpu_Vf, R, Rd); /* Vf = R & ~Rd */
+    tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15);
+
+    /* Zf */
+    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+
+    /* Nf */
+    tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
+
+    /* Sf */
+    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);/* Sf = Nf ^ Vf */
+
+    /* R */
+    tcg_gen_andi_tl(RdL, R, 0xff);
+    tcg_gen_shri_tl(RdH, R, 8);
+
+    tcg_temp_free_i32(Rd);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical AND between the contents of register Rd and register
+ *  Rr and places the result in the destination register Rd.
+ */
+static int avr_translate_AND(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[AND_Rd(opcode)];
+    TCGv Rr = cpu_r[AND_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_and_tl(R, Rd, Rr); /* Rd = Rd and Rr */
+
+    /* Vf */
+    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+
+    /* Zf */
+    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical AND between the contents of register Rd and a constant
+ *  and places the result in the destination register Rd.
+ */
+static int avr_translate_ANDI(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + ANDI_Rd(opcode)];
+    int Imm = (ANDI_Imm(opcode));
+
+    /* op */
+    tcg_gen_andi_tl(Rd, Rd, Imm); /* Rd = Rd & Imm */
+
+    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+    gen_ZNSf(Rd);
+
+    return BS_NONE;
+}
+
+/*
+ *  Shifts all bits in Rd one place to the right. Bit 7 is held constant. Bit 0
+ *  is loaded into the C Flag of the SREG. This operation effectively divides a
+ *  signed value by two without changing its sign. The Carry Flag can be used to
+ *  round the result.
+ */
+static int avr_translate_ASR(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[ASR_Rd(opcode)];
+    TCGv t1 = tcg_temp_new_i32();
+    TCGv t2 = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_andi_tl(t1, Rd, 0x80); /* t1 = (Rd & 0x80) | (Rd >> 1) */
+    tcg_gen_shri_tl(t2, Rd, 1);
+    tcg_gen_or_tl(t1, t1, t2);
+
+    /* Cf */
+    tcg_gen_andi_tl(cpu_Cf, Rd, 1); /* Cf = Rd(0) */
+
+    /* Vf */
+    tcg_gen_and_tl(cpu_Vf, cpu_Nf, cpu_Cf);/* Vf = Nf & Cf */
+
+    gen_ZNSf(t1);
+
+    /* op */
+    tcg_gen_mov_tl(Rd, t1);
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+
+    return BS_NONE;
+}
+
+/*
+ *  Clears a single Flag in SREG.
+ */
+static int avr_translate_BCLR(DisasContext *ctx, uint32_t opcode)
+{
+    switch (BCLR_Bit(opcode)) {
+    case 0x00:
+        tcg_gen_movi_tl(cpu_Cf, 0x00);
+        break;
+    case 0x01:
+        tcg_gen_movi_tl(cpu_Zf, 0x01);
+        break;
+    case 0x02:
+        tcg_gen_movi_tl(cpu_Nf, 0x00);
+        break;
+    case 0x03:
+        tcg_gen_movi_tl(cpu_Vf, 0x00);
+        break;
+    case 0x04:
+        tcg_gen_movi_tl(cpu_Sf, 0x00);
+        break;
+    case 0x05:
+        tcg_gen_movi_tl(cpu_Hf, 0x00);
+        break;
+    case 0x06:
+        tcg_gen_movi_tl(cpu_Tf, 0x00);
+        break;
+    case 0x07:
+        tcg_gen_movi_tl(cpu_If, 0x00);
+        break;
+    }
+
+    return BS_NONE;
+}
+
+/*
+ *  Copies the T Flag in the SREG (Status Register) to bit b in register Rd.
+ */
+static int avr_translate_BLD(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[BLD_Rd(opcode)];
+    TCGv t1 = tcg_temp_new_i32();
+
+    tcg_gen_andi_tl(Rd, Rd, ~(1u << BLD_Bit(opcode))); /* clear bit */
+    tcg_gen_shli_tl(t1, cpu_Tf, BLD_Bit(opcode)); /* create mask */
+    tcg_gen_or_tl(Rd, Rd, t1);
+
+    tcg_temp_free_i32(t1);
+
+    return BS_NONE;
+}
+
+/*
+ *  Conditional relative branch. Tests a single bit in SREG and branches
+ *  relatively to PC if the bit is cleared. This instruction branches relatively
+ *  to PC in either direction (PC - 63 < = destination <= PC + 64). The
+ *  parameter k is the offset from PC and is represented in two's complement
+ *  form.
+ */
+static int avr_translate_BRBC(DisasContext *ctx, uint32_t opcode)
+{
+    TCGLabel *taken = gen_new_label();
+    int Imm = sextract32(BRBC_Imm(opcode), 0, 7);
+
+    switch (BRBC_Bit(opcode)) {
+    case 0x00:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Cf, 0, taken);
+        break;
+    case 0x01:
+        tcg_gen_brcondi_i32(TCG_COND_NE, cpu_Zf, 0, taken);
+        break;
+    case 0x02:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Nf, 0, taken);
+        break;
+    case 0x03:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Vf, 0, taken);
+        break;
+    case 0x04:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Sf, 0, taken);
+        break;
+    case 0x05:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Hf, 0, taken);
+        break;
+    case 0x06:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Tf, 0, taken);
+        break;
+    case 0x07:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_If, 0, taken);
+        break;
+    }
+
+    gen_goto_tb(ctx, 1, ctx->inst[0].npc);
+    gen_set_label(taken);
+    gen_goto_tb(ctx, 0, ctx->inst[0].npc + Imm);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Conditional relative branch. Tests a single bit in SREG and branches
+ *  relatively to PC if the bit is set. This instruction branches relatively to
+ *  PC in either direction (PC - 63 < = destination <= PC + 64). The parameter k
+ *  is the offset from PC and is represented in two's complement form.
+ */
+static int avr_translate_BRBS(DisasContext *ctx, uint32_t opcode)
+{
+    TCGLabel *taken = gen_new_label();
+    int Imm = sextract32(BRBS_Imm(opcode), 0, 7);
+
+    switch (BRBS_Bit(opcode)) {
+    case 0x00:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Cf, 1, taken);
+        break;
+    case 0x01:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Zf, 0, taken);
+        break;
+    case 0x02:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Nf, 1, taken);
+        break;
+    case 0x03:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Vf, 1, taken);
+        break;
+    case 0x04:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Sf, 1, taken);
+        break;
+    case 0x05:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Hf, 1, taken);
+        break;
+    case 0x06:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_Tf, 1, taken);
+        break;
+    case 0x07:
+        tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_If, 1, taken);
+        break;
+    }
+
+    gen_goto_tb(ctx, 1, ctx->inst[0].npc);
+    gen_set_label(taken);
+    gen_goto_tb(ctx, 0, ctx->inst[0].npc + Imm);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Sets a single Flag or bit in SREG.
+ */
+static int avr_translate_BSET(DisasContext *ctx, uint32_t opcode)
+{
+    switch (BSET_Bit(opcode)) {
+    case 0x00:
+        tcg_gen_movi_tl(cpu_Cf, 0x01);
+        break;
+    case 0x01:
+        tcg_gen_movi_tl(cpu_Zf, 0x00);
+        break;
+    case 0x02:
+        tcg_gen_movi_tl(cpu_Nf, 0x01);
+        break;
+    case 0x03:
+        tcg_gen_movi_tl(cpu_Vf, 0x01);
+        break;
+    case 0x04:
+        tcg_gen_movi_tl(cpu_Sf, 0x01);
+        break;
+    case 0x05:
+        tcg_gen_movi_tl(cpu_Hf, 0x01);
+        break;
+    case 0x06:
+        tcg_gen_movi_tl(cpu_Tf, 0x01);
+        break;
+    case 0x07:
+        tcg_gen_movi_tl(cpu_If, 0x01);
+        break;
+    }
+
+    return BS_NONE;
+}
+
+/*
+ *  The BREAK instruction is used by the On-chip Debug system, and is
+ *  normally not used in the application software. When the BREAK instruction is
+ *  executed, the AVR CPU is set in the Stopped Mode. This gives the On-chip
+ *  Debugger access to internal resources.  If any Lock bits are set, or either
+ *  the JTAGEN or OCDEN Fuses are unprogrammed, the CPU will treat the BREAK
+ *  instruction as a NOP and will not enter the Stopped mode.  This instruction
+ *  is not available in all devices. Refer to the device specific instruction
+ *  set summary.
+ */
+static int avr_translate_BREAK(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_BREAK) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    /* TODO:   ??? */
+    return BS_NONE;
+}
+
+/*
+ *  Stores bit b from Rd to the T Flag in SREG (Status Register).
+ */
+static int avr_translate_BST(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[BST_Rd(opcode)];
+
+    tcg_gen_andi_tl(cpu_Tf, Rd, 1 << BST_Bit(opcode));
+    tcg_gen_shri_tl(cpu_Tf, cpu_Tf, BST_Bit(opcode));
+
+    return BS_NONE;
+}
+
+/*
+ *  Calls to a subroutine within the entire Program memory. The return
+ *  address (to the instruction after the CALL) will be stored onto the Stack.
+ *  (See also RCALL). The Stack Pointer uses a post-decrement scheme during
+ *  CALL.  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+static int avr_translate_CALL(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_JMP_CALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    int Imm = CALL_Imm(opcode);
+    int ret = ctx->inst[0].npc;
+
+    gen_push_ret(ctx, ret);
+    gen_goto_tb(ctx, 0, Imm);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Clears a specified bit in an I/O Register. This instruction operates on
+ *  the lower 32 I/O Registers -- addresses 0-31.
+ */
+static int avr_translate_CBI(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv data = tcg_temp_new_i32();
+    TCGv port = tcg_const_i32(CBI_Imm(opcode));
+
+    gen_helper_inb(data, cpu_env, port);
+    tcg_gen_andi_tl(data, data, ~(1 << CBI_Bit(opcode)));
+    gen_helper_outb(cpu_env, port, data);
+
+    tcg_temp_free_i32(data);
+    tcg_temp_free_i32(port);
+
+    return BS_NONE;
+}
+
+/*
+ *  Clears the specified bits in register Rd. Performs the logical AND
+ *  between the contents of register Rd and the complement of the constant mask
+ *  K. The result will be placed in register Rd.
+ */
+static int avr_translate_COM(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[COM_Rd(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    tcg_gen_xori_tl(Rd, Rd, 0xff);
+
+    tcg_gen_movi_tl(cpu_Cf, 1); /* Cf = 1 */
+    tcg_gen_movi_tl(cpu_Vf, 0); /* Vf = 0 */
+    gen_ZNSf(Rd);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a compare between two registers Rd and Rr.
+ *  None of the registers are changed. All conditional branches can be used
+ *  after this instruction.
+ */
+static int avr_translate_CP(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[CP_Rd(opcode)];
+    TCGv Rr = cpu_r[CP_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a compare between two registers Rd and Rr and
+ *  also takes into account the previous carry. None of the registers are
+ *  changed. All conditional branches can be used after this instruction.
+ */
+static int avr_translate_CPC(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[CPC_Rd(opcode)];
+    TCGv Rr = cpu_r[CPC_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+    tcg_gen_sub_tl(R, R, cpu_Cf);
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_NSf(R);
+
+    /* Previous value remains unchanged when the result is zero;
+     * cleared otherwise.
+     */
+    tcg_gen_or_tl(cpu_Zf, cpu_Zf, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a compare between register Rd and a constant.
+ *  The register is not changed. All conditional branches can be used after this
+ *  instruction.
+ */
+static int avr_translate_CPI(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + CPI_Rd(opcode)];
+    int Imm = CPI_Imm(opcode);
+    TCGv Rr = tcg_const_i32(Imm);
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    tcg_temp_free_i32(R);
+    tcg_temp_free_i32(Rr);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a compare between two registers Rd and Rr, and
+ *  skips the next instruction if Rd = Rr.
+ */
+static int avr_translate_CPSE(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[CPSE_Rd(opcode)];
+    TCGv Rr = cpu_r[CPSE_Rr(opcode)];
+    TCGLabel *skip = gen_new_label();
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_brcond_i32(TCG_COND_EQ, Rd, Rr, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Subtracts one -1- from the contents of register Rd and places the result
+ *  in the destination register Rd.  The C Flag in SREG is not affected by the
+ *  operation, thus allowing the DEC instruction to be used on a loop counter in
+ *  multiple-precision computations.  When operating on unsigned values, only
+ *  BREQ and BRNE branches can be expected to perform consistently.  When
+ *  operating on two's complement values, all signed branches are available.
+ */
+static int avr_translate_DEC(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[DEC_Rd(opcode)];
+
+    tcg_gen_subi_tl(Rd, Rd, 1); /* Rd = Rd - 1 */
+    tcg_gen_andi_tl(Rd, Rd, 0xff); /* make it 8 bits */
+
+        /* cpu_Vf = Rd == 0x7f */
+    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x7f);
+    gen_ZNSf(Rd);
+
+    return BS_NONE;
+}
+
+/*
+ *  The module is an instruction set extension to the AVR CPU, performing
+ *  DES iterations. The 64-bit data block (plaintext or ciphertext) is placed in
+ *  the CPU register file, registers R0-R7, where LSB of data is placed in LSB
+ *  of R0 and MSB of data is placed in MSB of R7. The full 64-bit key (including
+ *  parity bits) is placed in registers R8- R15, organized in the register file
+ *  with LSB of key in LSB of R8 and MSB of key in MSB of R15. Executing one DES
+ *  instruction performs one round in the DES algorithm. Sixteen rounds must be
+ *  executed in increasing order to form the correct DES ciphertext or
+ *  plaintext. Intermediate results are stored in the register file (R0-R15)
+ *  after each DES instruction. The instruction's operand (K) determines which
+ *  round is executed, and the half carry flag (H) determines whether encryption
+ *  or decryption is performed.  The DES algorithm is described in
+ *  "Specifications for the Data Encryption Standard" (Federal Information
+ *  Processing Standards Publication 46). Intermediate results in this
+ *  implementation differ from the standard because the initial permutation and
+ *  the inverse initial permutation are performed each iteration. This does not
+ *  affect the result in the final ciphertext or plaintext, but reduces
+ *  execution time.
+ */
+static int avr_translate_DES(DisasContext *ctx, uint32_t opcode)
+{
+    /* TODO: */
+    if (avr_feature(ctx->env, AVR_FEATURE_DES) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    return BS_NONE;
+}
+
+/*
+ *  Indirect call of a subroutine pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File and the EIND Register in the I/O space. This
+ *  instruction allows for indirect calls to the entire 4M (words) Program
+ *  memory space. See also ICALL. The Stack Pointer uses a post-decrement scheme
+ *  during EICALL.  This instruction is not available in all devices. Refer to
+ *  the device specific instruction set summary.
+ */
+static int avr_translate_EICALL(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_EIJMP_EICALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    int ret = ctx->inst[0].npc;
+
+    gen_push_ret(ctx, ret);
+
+    gen_jmp_ez();
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Indirect jump to the address pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File and the EIND Register in the I/O space. This
+ *  instruction allows for indirect jumps to the entire 4M (words) Program
+ *  memory space. See also IJMP.  This instruction is not available in all
+ *  devices. Refer to the device specific instruction set summary.
+ */
+static int avr_translate_EIJMP(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_EIJMP_EICALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    gen_jmp_ez();
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Loads one byte pointed to by the Z-register and the RAMPZ Register in
+ *  the I/O space, and places this byte in the destination register Rd. This
+ *  instruction features a 100% space effective constant initialization or
+ *  constant data fetch. The Program memory is organized in 16-bit words while
+ *  the Z-pointer is a byte address. Thus, the least significant bit of the
+ *  Z-pointer selects either low byte (ZLSB = 0) or high byte (ZLSB = 1). This
+ *  instruction can address the entire Program memory space. The Z-pointer
+ *  Register can either be left unchanged by the operation, or it can be
+ *  incremented. The incrementation applies to the entire 24-bit concatenation
+ *  of the RAMPZ and Z-pointer Registers.  Devices with Self-Programming
+ *  capability can use the ELPM instruction to read the Fuse and Lock bit value.
+ *  Refer to the device documentation for a detailed description.  This
+ *  instruction is not available in all devices. Refer to the device specific
+ *  instruction set summary.
+ */
+static int avr_translate_ELPM1(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_ELPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[0];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_ELPM2(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_ELPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[ELPM2_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_ELPMX(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_ELPMX) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[ELPMX_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical EOR between the contents of register Rd and
+ *  register Rr and places the result in the destination register Rd.
+ */
+static int avr_translate_EOR(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[EOR_Rd(opcode)];
+    TCGv Rr = cpu_r[EOR_Rr(opcode)];
+
+    tcg_gen_xor_tl(Rd, Rd, Rr);
+
+    tcg_gen_movi_tl(cpu_Vf, 0);
+    gen_ZNSf(Rd);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned
+ *  multiplication and shifts the result one bit left.
+ */
+static int avr_translate_FMUL(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + FMUL_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + FMUL_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
+    tcg_gen_shli_tl(R, R, 1);
+
+    tcg_gen_andi_tl(R0, R, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_andi_tl(R1, R, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
+ *  and shifts the result one bit left.
+ */
+static int avr_translate_FMULS(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + FMULS_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + FMULS_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+    tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
+    tcg_gen_mul_tl(R, t0, t1); /* R = Rd *Rr */
+    tcg_gen_shli_tl(R, R, 1);
+
+    tcg_gen_andi_tl(R0, R, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_andi_tl(R1, R, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
+ *  and shifts the result one bit left.
+ */
+static int avr_translate_FMULSU(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + FMULSU_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + FMULSU_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+    tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
+    tcg_gen_shli_tl(R, R, 1);
+
+    tcg_gen_andi_tl(R0, R, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_andi_tl(R1, R, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+    tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Calls to a subroutine within the entire 4M (words) Program memory. The
+ *  return address (to the instruction after the CALL) will be stored onto the
+ *  Stack. See also RCALL. The Stack Pointer uses a post-decrement scheme during
+ *  CALL.  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+static int avr_translate_ICALL(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_IJMP_ICALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    int ret = ctx->inst[0].npc;
+
+    gen_push_ret(ctx, ret);
+    gen_jmp_z();
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Indirect jump to the address pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File. The Z-pointer Register is 16 bits wide and
+ *  allows jump within the lowest 64K words (128KB) section of Program memory.
+ *  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+static int avr_translate_IJMP(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_IJMP_ICALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    gen_jmp_z();
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Loads data from the I/O Space (Ports, Timers, Configuration Registers,
+ *  etc.) into register Rd in the Register File.
+ */
+static int avr_translate_IN(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[IN_Rd(opcode)];
+    int Imm = IN_Imm(opcode);
+    TCGv port = tcg_const_i32(Imm);
+
+    gen_helper_inb(Rd, cpu_env, port);
+
+    tcg_temp_free_i32(port);
+
+    return BS_NONE;
+}
+
+/*
+ *  Adds one -1- to the contents of register Rd and places the result in the
+ *  destination register Rd.  The C Flag in SREG is not affected by the
+ *  operation, thus allowing the INC instruction to be used on a loop counter in
+ *  multiple-precision computations.  When operating on unsigned numbers, only
+ *  BREQ and BRNE branches can be expected to perform consistently. When
+ *  operating on two's complement values, all signed branches are available.
+ */
+static int avr_translate_INC(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[INC_Rd(opcode)];
+
+    tcg_gen_addi_tl(Rd, Rd, 1);
+    tcg_gen_andi_tl(Rd, Rd, 0xff);
+
+        /* cpu_Vf = Rd == 0x80 */
+    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x80);
+    gen_ZNSf(Rd);
+    return BS_NONE;
+}
+
+/*
+ *  Jump to an address within the entire 4M (words) Program memory. See also
+ *  RJMP.  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.0
+ */
+static int avr_translate_JMP(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_JMP_CALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    gen_goto_tb(ctx, 0, JMP_Imm(opcode));
+    return BS_BRANCH;
+}
+
+/*
+ *  Load one byte indirect from data space to register and stores an clear
+ *  the bits in data space specified by the register. The instruction can only
+ *  be used towards internal SRAM.  The data location is pointed to by the Z (16
+ *  bits) Pointer Register in the Register File. Memory access is limited to the
+ *  current data segment of 64KB. To access another data segment in devices with
+ *  more than 64KB data space, the RAMPZ in register in the I/O area has to be
+ *  changed.  The Z-pointer Register is left unchanged by the operation. This
+ *  instruction is especially suited for clearing status bits stored in SRAM.
+ */
+static void gen_data_store(DisasContext *ctx, TCGv data, TCGv addr)
+{
+    if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) {
+        gen_helper_fullwr(cpu_env, data, addr);
+    } else {
+        tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX); /* mem[addr] = data */
+    }
+}
+
+static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr)
+{
+    if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) {
+        gen_helper_fullrd(data, cpu_env, addr);
+    } else {
+        tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX); /* data = mem[addr] */
+    }
+}
+
+static int avr_translate_LAC(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rr = cpu_r[LAC_Rr(opcode)];
+    TCGv addr = gen_get_zaddr();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+        /* t1 = t0 & (0xff - Rr) = t0 and ~Rr */
+    tcg_gen_andc_tl(t1, t0, Rr);
+
+    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Load one byte indirect from data space to register and set bits in data
+ *  space specified by the register. The instruction can only be used towards
+ *  internal SRAM.  The data location is pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File. Memory access is limited to the current data
+ *  segment of 64KB. To access another data segment in devices with more than
+ *  64KB data space, the RAMPZ in register in the I/O area has to be changed.
+ *  The Z-pointer Register is left unchanged by the operation. This instruction
+ *  is especially suited for setting status bits stored in SRAM.
+ */
+static int avr_translate_LAS(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rr = cpu_r[LAS_Rr(opcode)];
+    TCGv addr = gen_get_zaddr();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+    tcg_gen_or_tl(t1, t0, Rr);
+
+    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Load one byte indirect from data space to register and toggles bits in
+ *  the data space specified by the register.  The instruction can only be used
+ *  towards SRAM.  The data location is pointed to by the Z (16 bits) Pointer
+ *  Register in the Register File. Memory access is limited to the current data
+ *  segment of 64KB. To access another data segment in devices with more than
+ *  64KB data space, the RAMPZ in register in the I/O area has to be changed.
+ *  The Z-pointer Register is left unchanged by the operation. This instruction
+ *  is especially suited for changing status bits stored in SRAM.
+ */
+static int avr_translate_LAT(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rr = cpu_r[LAT_Rr(opcode)];
+    TCGv addr = gen_get_zaddr();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+    tcg_gen_xor_tl(t1, t0, Rr);
+
+    tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+    gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte indirect from the data space to a register. For parts
+ *  with SRAM, the data space consists of the Register File, I/O memory and
+ *  internal SRAM (and external SRAM if applicable). For parts without SRAM, the
+ *  data space consists of the Register File only. In some parts the Flash
+ *  Memory has been mapped to the data space and can be read using this command.
+ *  The EEPROM has a separate address space.  The data location is pointed to by
+ *  the X (16 bits) Pointer Register in the Register File. Memory access is
+ *  limited to the current data segment of 64KB. To access another data segment
+ *  in devices with more than 64KB data space, the RAMPX in register in the I/O
+ *  area has to be changed.  The X-pointer Register can either be left unchanged
+ *  by the operation, or it can be post-incremented or predecremented.  These
+ *  features are especially suited for accessing arrays, tables, and Stack
+ *  Pointer usage of the X-pointer Register. Note that only the low byte of the
+ *  X-pointer is updated in devices with no more than 256 bytes data space. For
+ *  such devices, the high byte of the pointer is not used by this instruction
+ *  and can be used for other purposes. The RAMPX Register in the I/O area is
+ *  updated in parts with more than 64KB data space or more than 64KB Program
+ *  memory, and the increment/decrement is added to the entire 24-bit address on
+ *  such devices.  Not all variants of this instruction is available in all
+ *  devices. Refer to the device specific instruction set summary.  In the
+ *  Reduced Core tinyAVR the LD instruction can be used to achieve the same
+ *  operation as LPM since the program memory is mapped to the data memory
+ *  space.
+ */
+static int avr_translate_LDX1(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDX1_Rd(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    gen_data_load(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_LDX2(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDX2_Rd(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    gen_data_load(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_LDX3(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDX3_Rd(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_load(ctx, Rd, addr);
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte indirect with or without displacement from the data space
+ *  to a register. For parts with SRAM, the data space consists of the Register
+ *  File, I/O memory and internal SRAM (and external SRAM if applicable). For
+ *  parts without SRAM, the data space consists of the Register File only. In
+ *  some parts the Flash Memory has been mapped to the data space and can be
+ *  read using this command. The EEPROM has a separate address space.  The data
+ *  location is pointed to by the Y (16 bits) Pointer Register in the Register
+ *  File. Memory access is limited to the current data segment of 64KB. To
+ *  access another data segment in devices with more than 64KB data space, the
+ *  RAMPY in register in the I/O area has to be changed.  The Y-pointer Register
+ *  can either be left unchanged by the operation, or it can be post-incremented
+ *  or predecremented.  These features are especially suited for accessing
+ *  arrays, tables, and Stack Pointer usage of the Y-pointer Register. Note that
+ *  only the low byte of the Y-pointer is updated in devices with no more than
+ *  256 bytes data space. For such devices, the high byte of the pointer is not
+ *  used by this instruction and can be used for other purposes. The RAMPY
+ *  Register in the I/O area is updated in parts with more than 64KB data space
+ *  or more than 64KB Program memory, and the increment/decrement/displacement
+ *  is added to the entire 24-bit address on such devices.  Not all variants of
+ *  this instruction is available in all devices. Refer to the device specific
+ *  instruction set summary.  In the Reduced Core tinyAVR the LD instruction can
+ *  be used to achieve the same operation as LPM since the program memory is
+ *  mapped to the data memory space.
+ */
+static int avr_translate_LDY2(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDY2_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    gen_data_load(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_LDY3(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDY3_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_load(ctx, Rd, addr);
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_LDDY(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDDY_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    tcg_gen_addi_tl(addr, addr, LDDY_Imm(opcode)); /* addr = addr + q */
+    gen_data_load(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte indirect with or without displacement from the data space
+ *  to a register. For parts with SRAM, the data space consists of the Register
+ *  File, I/O memory and internal SRAM (and external SRAM if applicable). For
+ *  parts without SRAM, the data space consists of the Register File only. In
+ *  some parts the Flash Memory has been mapped to the data space and can be
+ *  read using this command. The EEPROM has a separate address space.  The data
+ *  location is pointed to by the Z (16 bits) Pointer Register in the Register
+ *  File. Memory access is limited to the current data segment of 64KB. To
+ *  access another data segment in devices with more than 64KB data space, the
+ *  RAMPZ in register in the I/O area has to be changed.  The Z-pointer Register
+ *  can either be left unchanged by the operation, or it can be post-incremented
+ *  or predecremented.  These features are especially suited for Stack Pointer
+ *  usage of the Z-pointer Register, however because the Z-pointer Register can
+ *  be used for indirect subroutine calls, indirect jumps and table lookup, it
+ *  is often more convenient to use the X or Y-pointer as a dedicated Stack
+ *  Pointer. Note that only the low byte of the Z-pointer is updated in devices
+ *  with no more than 256 bytes data space. For such devices, the high byte of
+ *  the pointer is not used by this instruction and can be used for other
+ *  purposes. The RAMPZ Register in the I/O area is updated in parts with more
+ *  than 64KB data space or more than 64KB Program memory, and the
+ *  increment/decrement/displacement is added to the entire 24-bit address on
+ *  such devices.  Not all variants of this instruction is available in all
+ *  devices. Refer to the device specific instruction set summary.  In the
+ *  Reduced Core tinyAVR the LD instruction can be used to achieve the same
+ *  operation as LPM since the program memory is mapped to the data memory
+ *  space.  For using the Z-pointer for table lookup in Program memory see the
+ *  LPM and ELPM instructions.
+ */
+static int avr_translate_LDZ2(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDZ2_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    gen_data_load(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_LDZ3(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDZ3_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_load(ctx, Rd, addr);
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_LDDZ(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDDZ_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_addi_tl(addr, addr, LDDZ_Imm(opcode));
+                                                    /* addr = addr + q */
+    gen_data_load(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+    Loads an 8 bit constant directly to register 16 to 31.
+ */
+static int avr_translate_LDI(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + LDI_Rd(opcode)];
+    int imm = LDI_Imm(opcode);
+
+    tcg_gen_movi_tl(Rd, imm);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte from the data space to a register. For parts with SRAM,
+ *  the data space consists of the Register File, I/O memory and internal SRAM
+ *  (and external SRAM if applicable). For parts without SRAM, the data space
+ *  consists of the register file only. The EEPROM has a separate address space.
+ *  A 16-bit address must be supplied. Memory access is limited to the current
+ *  data segment of 64KB. The LDS instruction uses the RAMPD Register to access
+ *  memory above 64KB. To access another data segment in devices with more than
+ *  64KB data space, the RAMPD in register in the I/O area has to be changed.
+ *  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+static int avr_translate_LDS(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LDS_Rd(opcode)];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_rampD;
+
+    tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
+    tcg_gen_shli_tl(addr, addr, 16);
+    tcg_gen_ori_tl(addr, addr, LDS_Imm(opcode));
+
+    gen_data_load(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Loads one byte pointed to by the Z-register into the destination
+ *  register Rd. This instruction features a 100% space effective constant
+ *  initialization or constant data fetch. The Program memory is organized in
+ *  16-bit words while the Z-pointer is a byte address. Thus, the least
+ *  significant bit of the Z-pointer selects either low byte (ZLSB = 0) or high
+ *  byte (ZLSB = 1). This instruction can address the first 64KB (32K words) of
+ *  Program memory. The Zpointer Register can either be left unchanged by the
+ *  operation, or it can be incremented. The incrementation does not apply to
+ *  the RAMPZ Register.  Devices with Self-Programming capability can use the
+ *  LPM instruction to read the Fuse and Lock bit values.  Refer to the device
+ *  documentation for a detailed description.  The LPM instruction is not
+ *  available in all devices. Refer to the device specific instruction set
+ *  summary
+ */
+static int avr_translate_LPM1(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_LPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[0];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_r[31];
+    TCGv L = cpu_r[30];
+
+    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+    tcg_gen_or_tl(addr, addr, L);
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_LPM2(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_LPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[LPM2_Rd(opcode)];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_r[31];
+    TCGv L = cpu_r[30];
+
+    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+    tcg_gen_or_tl(addr, addr, L);
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_LPMX(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_LPMX) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[LPMX_Rd(opcode)];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_r[31];
+    TCGv L = cpu_r[30];
+
+    tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+    tcg_gen_or_tl(addr, addr, L);
+
+    tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    tcg_gen_andi_tl(L, addr, 0xff);
+
+    tcg_gen_shri_tl(addr, addr, 8);
+    tcg_gen_andi_tl(H, addr, 0xff);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Shifts all bits in Rd one place to the right. Bit 7 is cleared. Bit 0 is
+ *  loaded into the C Flag of the SREG. This operation effectively divides an
+ *  unsigned value by two. The C Flag can be used to round the result.
+ */
+static int avr_translate_LSR(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[LSR_Rd(opcode)];
+
+    tcg_gen_andi_tl(cpu_Cf, Rd, 1);
+
+    tcg_gen_shri_tl(Rd, Rd, 1);
+
+    gen_ZNSf(Rd);
+    tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
+    return BS_NONE;
+}
+
+/*
+ *  This instruction makes a copy of one register into another. The source
+ *  register Rr is left unchanged, while the destination register Rd is loaded
+ *  with a copy of Rr.
+ */
+static int avr_translate_MOV(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[MOV_Rd(opcode)];
+    TCGv Rr = cpu_r[MOV_Rr(opcode)];
+
+    tcg_gen_mov_tl(Rd, Rr);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction makes a copy of one register pair into another register
+ *  pair. The source register pair Rr+1:Rr is left unchanged, while the
+ *  destination register pair Rd+1:Rd is loaded with a copy of Rr + 1:Rr.  This
+ *  instruction is not available in all devices. Refer to the device specific
+ *  instruction set summary.
+ */
+static int avr_translate_MOVW(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_MOVW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv RdL = cpu_r[MOVW_Rd(opcode) * 2 + 0];
+    TCGv RdH = cpu_r[MOVW_Rd(opcode) * 2 + 1];
+    TCGv RrL = cpu_r[MOVW_Rr(opcode) * 2 + 0];
+    TCGv RrH = cpu_r[MOVW_Rr(opcode) * 2 + 1];
+
+    tcg_gen_mov_tl(RdH, RrH);
+    tcg_gen_mov_tl(RdL, RrL);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication.
+ */
+static int avr_translate_MUL(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[MUL_Rd(opcode)];
+    TCGv Rr = cpu_r[MUL_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
+
+    tcg_gen_mov_tl(R0, R);
+    tcg_gen_andi_tl(R0, R0, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_mov_tl(R1, R);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
+    tcg_gen_mov_tl(cpu_Zf, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication.
+ */
+static int avr_translate_MULS(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + MULS_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + MULS_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+    tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
+    tcg_gen_mul_tl(R, t0, t1); /* R = Rd * Rr */
+
+    tcg_gen_mov_tl(R0, R);
+    tcg_gen_andi_tl(R0, R0, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_mov_tl(R1, R);
+    tcg_gen_andi_tl(R1, R0, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
+    tcg_gen_mov_tl(cpu_Zf, R);
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a
+ *  signed and an unsigned number.
+ */
+static int avr_translate_MULSU(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_MUL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv R0 = cpu_r[0];
+    TCGv R1 = cpu_r[1];
+    TCGv Rd = cpu_r[16 + MULSU_Rd(opcode)];
+    TCGv Rr = cpu_r[16 + MULSU_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+    tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
+
+    tcg_gen_mov_tl(R0, R);
+    tcg_gen_andi_tl(R0, R0, 0xff);
+    tcg_gen_shri_tl(R, R, 8);
+    tcg_gen_mov_tl(R1, R);
+    tcg_gen_andi_tl(R1, R0, 0xff);
+
+    tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+    tcg_gen_mov_tl(cpu_Zf, R);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Replaces the contents of register Rd with its two's complement; the
+ *  value $80 is left unchanged.
+ */
+static int avr_translate_NEG(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[SUB_Rd(opcode)];
+    TCGv t0 = tcg_const_i32(0);
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, t0, Rd); /* R = 0 - Rd */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, t0, Rd);
+    gen_sub_Vf(R, t0, Rd);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction performs a single cycle No Operation.
+ */
+static int avr_translate_NOP(DisasContext *ctx, uint32_t opcode)
+{
+
+    /* NOP */
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical OR between the contents of register Rd and register
+ *  Rr and places the result in the destination register Rd.
+ */
+static int avr_translate_OR(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[OR_Rd(opcode)];
+    TCGv Rr = cpu_r[OR_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    tcg_gen_or_tl(R, Rd, Rr);
+
+    tcg_gen_movi_tl(cpu_Vf, 0);
+    gen_ZNSf(R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Performs the logical OR between the contents of register Rd and a
+ *  constant and places the result in the destination register Rd.
+ */
+static int avr_translate_ORI(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + ORI_Rd(opcode)];
+    int Imm = (ORI_Imm(opcode));
+
+    tcg_gen_ori_tl(Rd, Rd, Imm); /* Rd = Rd | Imm */
+
+    tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+    gen_ZNSf(Rd);
+
+    return BS_NONE;
+}
+
+/*
+ *  Stores data from register Rr in the Register File to I/O Space (Ports,
+ *  Timers, Configuration Registers, etc.).
+ */
+static int avr_translate_OUT(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[OUT_Rd(opcode)];
+    int Imm = OUT_Imm(opcode);
+    TCGv port = tcg_const_i32(Imm);
+
+    gen_helper_outb(cpu_env, port, Rd);
+
+    tcg_temp_free_i32(port);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction loads register Rd with a byte from the STACK. The Stack
+ *  Pointer is pre-incremented by 1 before the POP.  This instruction is not
+ *  available in all devices. Refer to the device specific instruction set
+ *  summary.
+ */
+static int avr_translate_POP(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[POP_Rd(opcode)];
+
+    tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+    gen_data_load(ctx, Rd, cpu_sp);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction stores the contents of register Rr on the STACK. The
+ *  Stack Pointer is post-decremented by 1 after the PUSH.  This instruction is
+ *  not available in all devices. Refer to the device specific instruction set
+ *  summary.
+ */
+static int avr_translate_PUSH(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[PUSH_Rd(opcode)];
+
+    gen_data_store(ctx, Rd, cpu_sp);
+    tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+    return BS_NONE;
+}
+
+/*
+ *  Relative call to an address within PC - 2K + 1 and PC + 2K (words). The
+ *  return address (the instruction after the RCALL) is stored onto the Stack.
+ *  See also CALL. For AVR microcontrollers with Program memory not exceeding 4K
+ *  words (8KB) this instruction can address the entire memory from every
+ *  address location. The Stack Pointer uses a post-decrement scheme during
+ *  RCALL.
+ */
+static int avr_translate_RCALL(DisasContext *ctx, uint32_t opcode)
+{
+    int ret = ctx->inst[0].npc;
+    int dst = ctx->inst[0].npc + sextract32(RCALL_Imm(opcode), 0, 12);
+
+    gen_push_ret(ctx, ret);
+    gen_goto_tb(ctx, 0, dst);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Returns from subroutine. The return address is loaded from the STACK.
+ *  The Stack Pointer uses a preincrement scheme during RET.
+ */
+static int avr_translate_RET(DisasContext *ctx, uint32_t opcode)
+{
+    gen_pop_ret(ctx, cpu_pc);
+
+    tcg_gen_exit_tb(0);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Returns from interrupt. The return address is loaded from the STACK and
+ *  the Global Interrupt Flag is set.  Note that the Status Register is not
+ *  automatically stored when entering an interrupt routine, and it is not
+ *  restored when returning from an interrupt routine. This must be handled by
+ *  the application program. The Stack Pointer uses a pre-increment scheme
+ *  during RETI.
+ */
+static int avr_translate_RETI(DisasContext *ctx, uint32_t opcode)
+{
+    gen_pop_ret(ctx, cpu_pc);
+
+    tcg_gen_movi_tl(cpu_If, 1);
+
+    tcg_gen_exit_tb(0);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Relative jump to an address within PC - 2K +1 and PC + 2K (words). For
+ *  AVR microcontrollers with Program memory not exceeding 4K words (8KB) this
+ *  instruction can address the entire memory from every address location. See
+ *  also JMP.
+ */
+static int avr_translate_RJMP(DisasContext *ctx, uint32_t opcode)
+{
+    int dst = ctx->inst[0].npc + sextract32(RJMP_Imm(opcode), 0, 12);
+
+    gen_goto_tb(ctx, 0, dst);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Shifts all bits in Rd one place to the right. The C Flag is shifted into
+ *  bit 7 of Rd. Bit 0 is shifted into the C Flag.  This operation, combined
+ *  with ASR, effectively divides multi-byte signed values by two. Combined with
+ *  LSR it effectively divides multi-byte unsigned values by two. The Carry Flag
+ *  can be used to round the result.
+ */
+static int avr_translate_ROR(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[ROR_Rd(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t0, cpu_Cf, 7);
+    tcg_gen_andi_tl(cpu_Cf, Rd, 0);
+    tcg_gen_shri_tl(Rd, Rd, 1);
+    tcg_gen_or_tl(Rd, Rd, t0);
+
+    gen_ZNSf(Rd);
+    tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
+
+    tcg_temp_free_i32(t0);
+
+    return BS_NONE;
+}
+
+/*
+ *  Subtracts two registers and subtracts with the C Flag and places the
+ *  result in the destination register Rd.
+ */
+static int avr_translate_SBC(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[SBC_Rd(opcode)];
+    TCGv Rr = cpu_r[SBC_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+    tcg_gen_sub_tl(R, R, cpu_Cf);
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  SBCI -- Subtract Immediate with Carry
+ */
+static int avr_translate_SBCI(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + SBCI_Rd(opcode)];
+    TCGv Rr = tcg_const_i32(SBCI_Imm(opcode));
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+    tcg_gen_sub_tl(R, R, cpu_Cf);
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+    tcg_temp_free_i32(Rr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Sets a specified bit in an I/O Register. This instruction operates on
+ *  the lower 32 I/O Registers -- addresses 0-31.
+ */
+static int avr_translate_SBI(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv data = tcg_temp_new_i32();
+    TCGv port = tcg_const_i32(SBI_Imm(opcode));
+
+    gen_helper_inb(data, cpu_env, port);
+    tcg_gen_ori_tl(data, data, 1 << SBI_Bit(opcode));
+    gen_helper_outb(cpu_env, port, data);
+
+    tcg_temp_free_i32(port);
+    tcg_temp_free_i32(data);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction tests a single bit in an I/O Register and skips the
+ *  next instruction if the bit is cleared. This instruction operates on the
+ *  lower 32 I/O Registers -- addresses 0-31.
+ */
+static int avr_translate_SBIC(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv data = tcg_temp_new_i32();
+    TCGv port = tcg_const_i32(SBIC_Imm(opcode));
+    TCGLabel *skip = gen_new_label();
+
+    gen_helper_inb(data, cpu_env, port);
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_andi_tl(data, data, 1 << SBIC_Bit(opcode));
+    tcg_gen_brcondi_i32(TCG_COND_EQ, data, 0, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(port);
+    tcg_temp_free_i32(data);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  This instruction tests a single bit in an I/O Register and skips the
+ *  next instruction if the bit is set. This instruction operates on the lower
+ *  32 I/O Registers -- addresses 0-31.
+ */
+static int avr_translate_SBIS(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv data = tcg_temp_new_i32();
+    TCGv port = tcg_const_i32(SBIS_Imm(opcode));
+    TCGLabel *skip = gen_new_label();
+
+    gen_helper_inb(data, cpu_env, port);
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_andi_tl(data, data, 1 << SBIS_Bit(opcode));
+    tcg_gen_brcondi_i32(TCG_COND_NE, data, 0, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(port);
+    tcg_temp_free_i32(data);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  Subtracts an immediate value (0-63) from a register pair and places the
+ *  result in the register pair. This instruction operates on the upper four
+ *  register pairs, and is well suited for operations on the Pointer Registers.
+ *  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+static int avr_translate_SBIW(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv RdL = cpu_r[24 + 2 * SBIW_Rd(opcode)];
+    TCGv RdH = cpu_r[25 + 2 * SBIW_Rd(opcode)];
+    int Imm = (SBIW_Imm(opcode));
+    TCGv R = tcg_temp_new_i32();
+    TCGv Rd = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
+    tcg_gen_subi_tl(R, Rd, Imm); /* R = Rd - Imm */
+    tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
+
+    /* Cf */
+    tcg_gen_andc_tl(cpu_Cf, R, Rd);
+    tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15); /* Cf = R & ~Rd */
+
+    /* Vf */
+    tcg_gen_andc_tl(cpu_Vf, Rd, R);
+    tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15); /* Vf = Rd & ~R */
+
+    /* Zf */
+    tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+
+    /* Nf */
+    tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
+
+    /* Sf */
+    tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+
+    /* R */
+    tcg_gen_andi_tl(RdL, R, 0xff);
+    tcg_gen_shri_tl(RdH, R, 8);
+
+    tcg_temp_free_i32(Rd);
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction tests a single bit in a register and skips the next
+ *  instruction if the bit is cleared.
+ */
+static int avr_translate_SBRC(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rr = cpu_r[SBRC_Rr(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+    TCGLabel *skip = gen_new_label();
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_andi_tl(t0, Rr, 1 << SBRC_Bit(opcode));
+    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(t0);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  This instruction tests a single bit in a register and skips the next
+ *  instruction if the bit is set.
+ */
+static int avr_translate_SBRS(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rr = cpu_r[SBRS_Rr(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+    TCGLabel *skip = gen_new_label();
+
+        /* PC if next inst is skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
+    tcg_gen_andi_tl(t0, Rr, 1 << SBRS_Bit(opcode));
+    tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, skip);
+        /* PC if next inst is not skipped */
+    tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(t0);
+
+    return BS_BRANCH;
+}
+
+/*
+ *  This instruction sets the circuit in sleep mode defined by the MCU
+ *  Control Register.
+ */
+static int avr_translate_SLEEP(DisasContext *ctx, uint32_t opcode)
+{
+    gen_helper_sleep(cpu_env);
+
+    return BS_EXCP;
+}
+
+/*
+ *  SPM can be used to erase a page in the Program memory, to write a page
+ *  in the Program memory (that is already erased), and to set Boot Loader Lock
+ *  bits. In some devices, the Program memory can be written one word at a time,
+ *  in other devices an entire page can be programmed simultaneously after first
+ *  filling a temporary page buffer. In all cases, the Program memory must be
+ *  erased one page at a time. When erasing the Program memory, the RAMPZ and
+ *  Z-register are used as page address. When writing the Program memory, the
+ *  RAMPZ and Z-register are used as page or word address, and the R1:R0
+ *  register pair is used as data(1). When setting the Boot Loader Lock bits,
+ *  the R1:R0 register pair is used as data. Refer to the device documentation
+ *  for detailed description of SPM usage. This instruction can address the
+ *  entire Program memory.  The SPM instruction is not available in all devices.
+ *  Refer to the device specific instruction set summary.  Note: 1. R1
+ *  determines the instruction high byte, and R0 determines the instruction low
+ *  byte.
+ */
+static int avr_translate_SPM(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_SPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    /* TODO:   ??? */
+    return BS_NONE;
+}
+
+static int avr_translate_SPMX(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_SPMX) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    /* TODO:   ??? */
+    return BS_NONE;
+}
+
+static int avr_translate_STX1(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STX1_Rr(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    gen_data_store(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_STX2(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STX2_Rr(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    gen_data_store(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_STX3(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STX3_Rr(opcode)];
+    TCGv addr = gen_get_xaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_store(ctx, Rd, addr);
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_STY2(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STY2_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    gen_data_store(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_STY3(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STY3_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_store(ctx, Rd, addr);
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_STDY(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STDY_Rd(opcode)];
+    TCGv addr = gen_get_yaddr();
+
+    tcg_gen_addi_tl(addr, addr, STDY_Imm(opcode));
+                                                /* addr = addr + q */
+    gen_data_store(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_STZ2(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STZ2_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    gen_data_store(ctx, Rd, addr);
+    tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_STZ3(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STZ3_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+    gen_data_store(ctx, Rd, addr);
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+static int avr_translate_STDZ(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STDZ_Rd(opcode)];
+    TCGv addr = gen_get_zaddr();
+
+    tcg_gen_addi_tl(addr, addr, STDZ_Imm(opcode));
+                                                    /* addr = addr + q */
+    gen_data_store(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Stores one byte from a Register to the data space. For parts with SRAM,
+ *  the data space consists of the Register File, I/O memory and internal SRAM
+ *  (and external SRAM if applicable). For parts without SRAM, the data space
+ *  consists of the Register File only. The EEPROM has a separate address space.
+ *  A 16-bit address must be supplied. Memory access is limited to the current
+ *  data segment of 64KB. The STS instruction uses the RAMPD Register to access
+ *  memory above 64KB. To access another data segment in devices with more than
+ *  64KB data space, the RAMPD in register in the I/O area has to be changed.
+ *  This instruction is not available in all devices. Refer to the device
+ *  specific instruction set summary.
+ */
+static int avr_translate_STS(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[STS_Rd(opcode)];
+    TCGv addr = tcg_temp_new_i32();
+    TCGv H = cpu_rampD;
+
+    tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
+    tcg_gen_shli_tl(addr, addr, 16);
+    tcg_gen_ori_tl(addr, addr, STS_Imm(opcode));
+
+    gen_data_store(ctx, Rd, addr);
+
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Subtracts two registers and places the result in the destination
+ *  register Rd.
+ */
+static int avr_translate_SUB(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[SUB_Rd(opcode)];
+    TCGv Rr = cpu_r[SUB_Rr(opcode)];
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+
+    return BS_NONE;
+}
+
+/*
+ *  Subtracts a register and a constant and places the result in the
+ *  destination register Rd. This instruction is working on Register R16 to R31
+ *  and is very well suited for operations on the X, Y, and Z-pointers.
+ */
+static int avr_translate_SUBI(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[16 + SUBI_Rd(opcode)];
+    TCGv Rr = tcg_const_i32(SUBI_Imm(opcode));
+    TCGv R = tcg_temp_new_i32();
+
+    /* op */
+    tcg_gen_sub_tl(R, Rd, Rr);
+                                                    /* R = Rd - Imm */
+    tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+
+    gen_sub_CHf(R, Rd, Rr);
+    gen_sub_Vf(R, Rd, Rr);
+    gen_ZNSf(R);
+
+    /* R */
+    tcg_gen_mov_tl(Rd, R);
+
+    tcg_temp_free_i32(R);
+    tcg_temp_free_i32(Rr);
+
+    return BS_NONE;
+}
+
+/*
+ *  Swaps high and low nibbles in a register.
+ */
+static int avr_translate_SWAP(DisasContext *ctx, uint32_t opcode)
+{
+    TCGv Rd = cpu_r[SWAP_Rd(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new_i32();
+
+    tcg_gen_andi_tl(t0, Rd, 0x0f);
+    tcg_gen_shli_tl(t0, t0, 4);
+    tcg_gen_andi_tl(t1, Rd, 0xf0);
+    tcg_gen_shri_tl(t1, t1, 4);
+    tcg_gen_or_tl(Rd, t0, t1);
+
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t0);
+
+    return BS_NONE;
+}
+
+/*
+ *  This instruction resets the Watchdog Timer. This instruction must be
+ *  executed within a limited time given by the WD prescaler. See the Watchdog
+ *  Timer hardware specification.
+ */
+static int avr_translate_WDR(DisasContext *ctx, uint32_t opcode)
+{
+    gen_helper_wdr(cpu_env);
+
+    return BS_NONE;
+}
+
+/*
+ *  Exchanges one byte indirect between register and data space.  The data
+ *  location is pointed to by the Z (16 bits) Pointer Register in the Register
+ *  File. Memory access is limited to the current data segment of 64KB. To
+ *  access another data segment in devices with more than 64KB data space, the
+ *  RAMPZ in register in the I/O area has to be changed.  The Z-pointer Register
+ *  is left unchanged by the operation. This instruction is especially suited
+ *  for writing/reading status bits stored in SRAM.
+ */
+static int avr_translate_XCH(DisasContext *ctx, uint32_t opcode)
+{
+    if (avr_feature(ctx->env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv Rd = cpu_r[XCH_Rd(opcode)];
+    TCGv t0 = tcg_temp_new_i32();
+    TCGv addr = gen_get_zaddr();
+
+    gen_data_load(ctx, t0, addr);
+    gen_data_store(ctx, Rd, addr);
+    tcg_gen_mov_tl(Rd, t0);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return BS_NONE;
+}
+
 #include "decode.inc.c"
 
 void avr_translate_init(void)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH v18 00/13] AVR target
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (12 preceding siblings ...)
  2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 13/13] target-avr: Merge translate-inst.inc.c into translate.c Richard Henderson
@ 2016-09-16 22:34 ` no-reply
  2016-09-17 19:55 ` Michael Rolnik
  14 siblings, 0 replies; 16+ messages in thread
From: no-reply @ 2016-09-16 22:34 UTC (permalink / raw)
  To: rth; +Cc: famz, qemu-devel, mrolnik

Hi,

Your series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 1474063242-27419-1-git-send-email-rth@twiddle.net
Subject: [Qemu-devel] [PATCH v18 00/13] AVR target

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
58f0bcb target-avr: Merge translate-inst.inc.c into translate.c
f0b4956 target-avr: Respect .inc.c convention
390da65 target-avr: Put all translation code into one compilation unit
93e0b30 target-avr: Put env pointer in DisasContext
8862669 target-avr: adding instruction decoder
1b8ab42 target-avr: instruction decoder generator
a243c5a target-avr: adding instruction translation
72ba9fc target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions
f85d68f target-avr: adding AVR interrupt handling
7a9f664 target-avr: adding instructions encodings
b7a16a1 target-avr: adding a sample AVR board
140ca0e target-avr: adding AVR CPU features/flavors
7049535 target-avr: AVR cores support is added.

=== OUTPUT BEGIN ===
Checking PATCH 1/13: target-avr: AVR cores support is added....
Checking PATCH 2/13: target-avr: adding AVR CPU features/flavors...
Checking PATCH 3/13: target-avr: adding a sample AVR board...
Checking PATCH 4/13: target-avr: adding instructions encodings...
Checking PATCH 5/13: target-avr: adding AVR interrupt handling...
Checking PATCH 6/13: target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions...
Checking PATCH 7/13: target-avr: adding instruction translation...
Checking PATCH 8/13: target-avr: instruction decoder generator...
ERROR: suspect code indent for conditional statements (4, 4)
#810: FILE: target-avr/cpugen/src/cpugen.cpp:440:
+    if (argc != 2) {
[...]
+    }

total: 1 errors, 0 warnings, 1220 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 9/13: target-avr: adding instruction decoder...
Checking PATCH 10/13: target-avr: Put env pointer in DisasContext...
ERROR: "foo* bar" should be "foo *bar"
#1119: FILE: target-avr/translate-inst.h:26:
+int avr_translate_NOP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1122: FILE: target-avr/translate-inst.h:28:
+int avr_translate_MOVW(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1131: FILE: target-avr/translate-inst.h:39:
+int avr_translate_MULS(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1140: FILE: target-avr/translate-inst.h:50:
+int avr_translate_MULSU(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1149: FILE: target-avr/translate-inst.h:61:
+int avr_translate_FMUL(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1158: FILE: target-avr/translate-inst.h:72:
+int avr_translate_FMULS(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1167: FILE: target-avr/translate-inst.h:83:
+int avr_translate_FMULSU(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1176: FILE: target-avr/translate-inst.h:94:
+int avr_translate_CPC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1185: FILE: target-avr/translate-inst.h:106:
+int avr_translate_SBC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1194: FILE: target-avr/translate-inst.h:118:
+int avr_translate_ADD(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1203: FILE: target-avr/translate-inst.h:130:
+int avr_translate_AND(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1212: FILE: target-avr/translate-inst.h:142:
+int avr_translate_EOR(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1221: FILE: target-avr/translate-inst.h:154:
+int avr_translate_OR(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1230: FILE: target-avr/translate-inst.h:166:
+int avr_translate_MOV(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1239: FILE: target-avr/translate-inst.h:178:
+int avr_translate_CPSE(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1248: FILE: target-avr/translate-inst.h:190:
+int avr_translate_CP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1257: FILE: target-avr/translate-inst.h:202:
+int avr_translate_SUB(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1266: FILE: target-avr/translate-inst.h:214:
+int avr_translate_ADC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1275: FILE: target-avr/translate-inst.h:226:
+int avr_translate_CPI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1284: FILE: target-avr/translate-inst.h:238:
+int avr_translate_SBCI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1293: FILE: target-avr/translate-inst.h:250:
+int avr_translate_ORI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1302: FILE: target-avr/translate-inst.h:262:
+int avr_translate_SUBI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1311: FILE: target-avr/translate-inst.h:274:
+int avr_translate_ANDI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1320: FILE: target-avr/translate-inst.h:286:
+int avr_translate_LDDZ(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1329: FILE: target-avr/translate-inst.h:299:
+int avr_translate_LDDY(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1338: FILE: target-avr/translate-inst.h:312:
+int avr_translate_STDZ(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1347: FILE: target-avr/translate-inst.h:325:
+int avr_translate_STDY(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1356: FILE: target-avr/translate-inst.h:338:
+int avr_translate_LDS(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1365: FILE: target-avr/translate-inst.h:349:
+int avr_translate_LDZ2(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1372: FILE: target-avr/translate-inst.h:355:
+int avr_translate_LDZ3(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1379: FILE: target-avr/translate-inst.h:361:
+int avr_translate_LPM2(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1386: FILE: target-avr/translate-inst.h:367:
+int avr_translate_LPMX(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1393: FILE: target-avr/translate-inst.h:373:
+int avr_translate_ELPM2(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1400: FILE: target-avr/translate-inst.h:379:
+int avr_translate_ELPMX(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1407: FILE: target-avr/translate-inst.h:385:
+int avr_translate_LDY2(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1414: FILE: target-avr/translate-inst.h:391:
+int avr_translate_LDY3(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1421: FILE: target-avr/translate-inst.h:397:
+int avr_translate_LDX1(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1428: FILE: target-avr/translate-inst.h:403:
+int avr_translate_LDX2(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1435: FILE: target-avr/translate-inst.h:409:
+int avr_translate_LDX3(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1442: FILE: target-avr/translate-inst.h:415:
+int avr_translate_POP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1449: FILE: target-avr/translate-inst.h:421:
+int avr_translate_STS(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1458: FILE: target-avr/translate-inst.h:432:
+int avr_translate_STZ2(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1465: FILE: target-avr/translate-inst.h:438:
+int avr_translate_STZ3(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1472: FILE: target-avr/translate-inst.h:444:
+int avr_translate_XCH(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1479: FILE: target-avr/translate-inst.h:450:
+int avr_translate_LAS(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1486: FILE: target-avr/translate-inst.h:456:
+int avr_translate_LAC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1493: FILE: target-avr/translate-inst.h:462:
+int avr_translate_LAT(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1500: FILE: target-avr/translate-inst.h:468:
+int avr_translate_STY2(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1507: FILE: target-avr/translate-inst.h:474:
+int avr_translate_STY3(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1514: FILE: target-avr/translate-inst.h:480:
+int avr_translate_STX1(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1521: FILE: target-avr/translate-inst.h:486:
+int avr_translate_STX2(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1528: FILE: target-avr/translate-inst.h:492:
+int avr_translate_STX3(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1535: FILE: target-avr/translate-inst.h:498:
+int avr_translate_PUSH(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1542: FILE: target-avr/translate-inst.h:504:
+int avr_translate_COM(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1549: FILE: target-avr/translate-inst.h:510:
+int avr_translate_NEG(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1556: FILE: target-avr/translate-inst.h:516:
+int avr_translate_SWAP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1563: FILE: target-avr/translate-inst.h:522:
+int avr_translate_INC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1570: FILE: target-avr/translate-inst.h:528:
+int avr_translate_ASR(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1577: FILE: target-avr/translate-inst.h:534:
+int avr_translate_LSR(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1584: FILE: target-avr/translate-inst.h:540:
+int avr_translate_ROR(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1591: FILE: target-avr/translate-inst.h:546:
+int avr_translate_BSET(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1598: FILE: target-avr/translate-inst.h:552:
+int avr_translate_IJMP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1601: FILE: target-avr/translate-inst.h:554:
+int avr_translate_EIJMP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1604: FILE: target-avr/translate-inst.h:556:
+int avr_translate_BCLR(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1611: FILE: target-avr/translate-inst.h:562:
+int avr_translate_RET(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1614: FILE: target-avr/translate-inst.h:564:
+int avr_translate_RETI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1617: FILE: target-avr/translate-inst.h:566:
+int avr_translate_ICALL(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1620: FILE: target-avr/translate-inst.h:568:
+int avr_translate_EICALL(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1623: FILE: target-avr/translate-inst.h:570:
+int avr_translate_SLEEP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1626: FILE: target-avr/translate-inst.h:572:
+int avr_translate_BREAK(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1629: FILE: target-avr/translate-inst.h:574:
+int avr_translate_WDR(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1632: FILE: target-avr/translate-inst.h:576:
+int avr_translate_LPM1(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1635: FILE: target-avr/translate-inst.h:578:
+int avr_translate_ELPM1(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1638: FILE: target-avr/translate-inst.h:580:
+int avr_translate_SPM(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1641: FILE: target-avr/translate-inst.h:582:
+int avr_translate_SPMX(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1644: FILE: target-avr/translate-inst.h:584:
+int avr_translate_DEC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1651: FILE: target-avr/translate-inst.h:590:
+int avr_translate_DES(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1658: FILE: target-avr/translate-inst.h:596:
+int avr_translate_JMP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1666: FILE: target-avr/translate-inst.h:603:
+int avr_translate_CALL(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1674: FILE: target-avr/translate-inst.h:610:
+int avr_translate_ADIW(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1683: FILE: target-avr/translate-inst.h:622:
+int avr_translate_SBIW(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1692: FILE: target-avr/translate-inst.h:634:
+int avr_translate_CBI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1701: FILE: target-avr/translate-inst.h:645:
+int avr_translate_SBIC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1710: FILE: target-avr/translate-inst.h:656:
+int avr_translate_SBI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1719: FILE: target-avr/translate-inst.h:667:
+int avr_translate_SBIS(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1728: FILE: target-avr/translate-inst.h:678:
+int avr_translate_MUL(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1737: FILE: target-avr/translate-inst.h:690:
+int avr_translate_IN(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1746: FILE: target-avr/translate-inst.h:702:
+int avr_translate_OUT(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1755: FILE: target-avr/translate-inst.h:714:
+int avr_translate_RJMP(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1762: FILE: target-avr/translate-inst.h:720:
+int avr_translate_LDI(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1771: FILE: target-avr/translate-inst.h:732:
+int avr_translate_RCALL(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1778: FILE: target-avr/translate-inst.h:738:
+int avr_translate_BRBS(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1787: FILE: target-avr/translate-inst.h:749:
+int avr_translate_BRBC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1796: FILE: target-avr/translate-inst.h:760:
+int avr_translate_BLD(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1805: FILE: target-avr/translate-inst.h:771:
+int avr_translate_BST(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1814: FILE: target-avr/translate-inst.h:782:
+int avr_translate_SBRC(DisasContext* ctx, uint32_t opcode);

ERROR: "foo* bar" should be "foo *bar"
#1823: FILE: target-avr/translate-inst.h:793:
+int avr_translate_SBRS(DisasContext* ctx, uint32_t opcode);

total: 97 errors, 0 warnings, 1743 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 11/13: target-avr: Put all translation code into one compilation unit...
ERROR: externs should be avoided in .c files
#1615: FILE: target-avr/translate.c:64:
+uint32_t get_opcode(uint8_t const *code, unsigned bitBase, unsigned bitSize);

total: 1 errors, 0 warnings, 1493 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 12/13: target-avr: Respect .inc.c convention...
Checking PATCH 13/13: target-avr: Merge translate-inst.inc.c into translate.c...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH v18 00/13] AVR target
  2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
                   ` (13 preceding siblings ...)
  2016-09-16 22:34 ` [Qemu-devel] [PATCH v18 00/13] AVR target no-reply
@ 2016-09-17 19:55 ` Michael Rolnik
  14 siblings, 0 replies; 16+ messages in thread
From: Michael Rolnik @ 2016-09-17 19:55 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers

Thank you Richard.


On Sat, Sep 17, 2016 at 1:00 AM, Richard Henderson <rth@twiddle.net> wrote:

> This is Michael's v17, with some adjustments of my own:
>
> (1) Fix the whitespace errors reported by "git am",
> (2) Replace the utf-8 characters with normal ascii,
> (3) Ditch the separate compilation of translate.c.
>
> I retained the two separate files that could be regenerated
> from the included cpugen program, but merged in translate-insn.c.
> Not that it matters, but the code generated is about 3k smaller.
>
>
> r~
>
>
> Michael Rolnik (9):
>   target-avr: AVR cores support is added.
>   target-avr: adding AVR CPU features/flavors
>   target-avr: adding a sample AVR board
>   target-avr: adding instructions encodings
>   target-avr: adding AVR interrupt handling
>   target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported
>     instructions
>   target-avr: adding instruction translation
>   target-avr: instruction decoder generator
>   target-avr: adding instruction decoder
>
> Richard Henderson (4):
>   target-avr: Put env pointer in DisasContext
>   target-avr: Put all translation code into one compilation unit
>   target-avr: Respect .inc.c convention
>   target-avr: Merge translate-inst.inc.c into translate.c
>
>  MAINTAINERS                                |    6 +
>  arch_init.c                                |    2 +
>  configure                                  |    5 +
>  default-configs/avr-softmmu.mak            |   21 +
>  hw/avr/Makefile.objs                       |   21 +
>  hw/avr/sample.c                            |  111 ++
>  include/disas/bfd.h                        |    6 +
>  include/sysemu/arch_init.h                 |    1 +
>  target-avr/Makefile.objs                   |   23 +
>  target-avr/cpu-qom.h                       |   84 +
>  target-avr/cpu.c                           |  602 ++++++
>  target-avr/cpu.h                           |  237 +++
>  target-avr/cpugen/CMakeLists.txt           |   38 +
>  target-avr/cpugen/README.md                |   17 +
>  target-avr/cpugen/cpu/avr.yaml             |  213 ++
>  target-avr/cpugen/src/CMakeLists.txt       |   62 +
>  target-avr/cpugen/src/cpugen.cpp           |  457 +++++
>  target-avr/cpugen/src/utils.cpp            |   26 +
>  target-avr/cpugen/src/utils.h              |   78 +
>  target-avr/cpugen/xsl/decode.c.xsl         |  103 +
>  target-avr/cpugen/xsl/translate-inst.h.xsl |  118 ++
>  target-avr/cpugen/xsl/utils.xsl            |  108 ++
>  target-avr/decode.inc.c                    |  689 +++++++
>  target-avr/gdbstub.c                       |   85 +
>  target-avr/helper.c                        |  355 ++++
>  target-avr/helper.h                        |   28 +
>  target-avr/machine.c                       |  114 ++
>  target-avr/translate-inst.h                |  691 +++++++
>  target-avr/translate.c                     | 2911
> ++++++++++++++++++++++++++++
>  29 files changed, 7212 insertions(+)
>  create mode 100644 default-configs/avr-softmmu.mak
>  create mode 100644 hw/avr/Makefile.objs
>  create mode 100644 hw/avr/sample.c
>  create mode 100644 target-avr/Makefile.objs
>  create mode 100644 target-avr/cpu-qom.h
>  create mode 100644 target-avr/cpu.c
>  create mode 100644 target-avr/cpu.h
>  create mode 100644 target-avr/cpugen/CMakeLists.txt
>  create mode 100644 target-avr/cpugen/README.md
>  create mode 100644 target-avr/cpugen/cpu/avr.yaml
>  create mode 100644 target-avr/cpugen/src/CMakeLists.txt
>  create mode 100644 target-avr/cpugen/src/cpugen.cpp
>  create mode 100644 target-avr/cpugen/src/utils.cpp
>  create mode 100644 target-avr/cpugen/src/utils.h
>  create mode 100644 target-avr/cpugen/xsl/decode.c.xsl
>  create mode 100644 target-avr/cpugen/xsl/translate-inst.h.xsl
>  create mode 100644 target-avr/cpugen/xsl/utils.xsl
>  create mode 100644 target-avr/decode.inc.c
>  create mode 100644 target-avr/gdbstub.c
>  create mode 100644 target-avr/helper.c
>  create mode 100644 target-avr/helper.h
>  create mode 100644 target-avr/machine.c
>  create mode 100644 target-avr/translate-inst.h
>  create mode 100644 target-avr/translate.c
>
> --
> 2.7.4
>
>


-- 
Best Regards,
Michael Rolnik

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2016-09-17 19:56 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-16 22:00 [Qemu-devel] [PATCH v18 00/13] AVR target Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 01/13] target-avr: AVR cores support is added Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 02/13] target-avr: adding AVR CPU features/flavors Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 03/13] target-avr: adding a sample AVR board Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 04/13] target-avr: adding instructions encodings Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 05/13] target-avr: adding AVR interrupt handling Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 06/13] target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 07/13] target-avr: adding instruction translation Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 08/13] target-avr: instruction decoder generator Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 09/13] target-avr: adding instruction decoder Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 10/13] target-avr: Put env pointer in DisasContext Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 11/13] target-avr: Put all translation code into one compilation unit Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 12/13] target-avr: Respect .inc.c convention Richard Henderson
2016-09-16 22:00 ` [Qemu-devel] [PATCH v18 13/13] target-avr: Merge translate-inst.inc.c into translate.c Richard Henderson
2016-09-16 22:34 ` [Qemu-devel] [PATCH v18 00/13] AVR target no-reply
2016-09-17 19:55 ` Michael Rolnik

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.