All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions
@ 2016-05-30  1:23 Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 2/9] adding AVR CPU features/flavors Michael Rolnik
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 arch_init.c                     |   2 +
 configure                       |   5 +
 default-configs/avr-softmmu.mak |   1 +
 disas/Makefile.objs             |   1 +
 disas/avr.c                     |  10 ++
 include/disas/bfd.h             |   7 +
 include/sysemu/arch_init.h      |   1 +
 target-avr/Makefile.objs        |   3 +
 target-avr/cpu-qom.h            |  97 +++++++++++++
 target-avr/cpu.c                | 315 ++++++++++++++++++++++++++++++++++++++++
 target-avr/cpu.h                | 152 +++++++++++++++++++
 target-avr/gdbstub.c            | 105 ++++++++++++++
 target-avr/helper.c             | 105 ++++++++++++++
 target-avr/helper.h             |  21 +++
 target-avr/machine.c            |  54 +++++++
 target-avr/machine.h            |  21 +++
 target-avr/translate.c          | 300 ++++++++++++++++++++++++++++++++++++++
 17 files changed, 1200 insertions(+)
 create mode 100644 default-configs/avr-softmmu.mak
 create mode 100644 disas/avr.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/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/machine.h
 create mode 100644 target-avr/translate.c

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 b5aab72..90af399 100755
--- a/configure
+++ b/configure
@@ -5630,6 +5630,8 @@ case "$target_name" in
   x86_64)
     TARGET_BASE_ARCH=i386
   ;;
+  avr)
+  ;;
   alpha)
   ;;
   arm|armeb)
@@ -5826,6 +5828,9 @@ disas_config() {
 
 for i in $ARCH $TARGET_BASE_ARCH ; do
   case "$i" in
+  avr)
+    disas_config "AVR"
+  ;;
   alpha)
     disas_config "ALPHA"
   ;;
diff --git a/default-configs/avr-softmmu.mak b/default-configs/avr-softmmu.mak
new file mode 100644
index 0000000..ca94aad
--- /dev/null
+++ b/default-configs/avr-softmmu.mak
@@ -0,0 +1 @@
+# Default configuration for avr-softmmu
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index abeba84..218e434 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -21,6 +21,7 @@ common-obj-$(CONFIG_S390_DIS) += s390.o
 common-obj-$(CONFIG_SH4_DIS) += sh4.o
 common-obj-$(CONFIG_SPARC_DIS) += sparc.o
 common-obj-$(CONFIG_LM32_DIS) += lm32.o
+common-obj-$(CONFIG_AVR_DIS) += avr.o
 
 # TODO: As long as the TCG interpreter and its generated code depend
 # on the QEMU target, we cannot compile the disassembler here.
diff --git a/disas/avr.c b/disas/avr.c
new file mode 100644
index 0000000..f916e72
--- /dev/null
+++ b/disas/avr.c
@@ -0,0 +1,10 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "disas/bfd.h"
+
+int print_insn_avr(bfd_vma addr, disassemble_info *info)
+{
+    int length  = 0;;
+    /*  TODO    */
+    return length;
+}
diff --git a/include/disas/bfd.h b/include/disas/bfd.h
index a112e9c..04e2201 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
@@ -415,6 +421,7 @@ int print_insn_crisv10          (bfd_vma, disassemble_info*);
 int print_insn_microblaze       (bfd_vma, disassemble_info*);
 int print_insn_ia64             (bfd_vma, disassemble_info*);
 int print_insn_lm32             (bfd_vma, disassemble_info*);
+int print_insn_avr              (bfd_vma, disassemble_info*);
 
 #if 0
 /* Fetch the disassembler for a given BFD, if that support is available.  */
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index d690dfa..8c75777 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..c503546
--- /dev/null
+++ b/target-avr/Makefile.objs
@@ -0,0 +1,3 @@
+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..76ca908
--- /dev/null
+++ b/target-avr/cpu-qom.h
@@ -0,0 +1,97 @@
+/*
+ * 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 vmstate_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..ff26018
--- /dev/null
+++ b/target-avr/cpu.c
@@ -0,0 +1,315 @@
+/*
+ * 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"
+#include "machine.h"
+
+static void         avr_cpu_set_pc(
+                                CPUState           *cs,
+                                vaddr               value)
+{
+    AVRCPU   *cpu = AVR_CPU(cs);
+
+    cpu->env.pc = value / 2;    /*  internaly PC points to words, not bytes */
+}
+
+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     = tb->pc / 2;
+}
+
+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);
+
+    memset(env, 0, sizeof(CPUAVRState));
+    env->pc         = 0;
+    env->sregI      = 1;
+
+    tlb_flush(s, 1);
+}
+
+static void         avr_cpu_disas_set_info(
+                                CPUState           *cpu,
+                                disassemble_info   *info)
+{
+    info->mach      = bfd_arch_avr;
+    info->print_insn = print_insn_avr;
+}
+
+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                = &vmstate_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;
+}
+
+static void         avr_any_initfn(
+                                Object             *obj)
+{
+    /* Set cpu feature flags */
+}
+
+typedef struct AVRCPUInfo {
+    const char     *name;
+    void (*initfn)(Object *obj);
+} AVRCPUInfo;
+
+static const AVRCPUInfo avr_cpus[] = {
+    {   .name = "any",      .initfn = avr_any_initfn },
+};
+
+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);
+    if (strcmp(name_a, "any-" TYPE_AVR_CPU) == 0) {
+        return 1;
+    } else if (strcmp(name_b, "any-" TYPE_AVR_CPU) == 0) {
+        return -1;
+    } else {
+        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..3692329
--- /dev/null
+++ b/target-avr/cpu.h
@@ -0,0 +1,152 @@
+/*
+ * 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
+
+#define TARGET_IS_LIENDIAN 1
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat.h"
+
+#define TARGET_PAGE_BITS            8
+#define TARGET_PHYS_ADDR_SPACE_BITS 24
+#define TARGET_VIRT_ADDR_SPACE_BITS 24
+#define NB_MMU_MODES                2
+
+#define CODE_INDEX                  0
+#define DATA_INDEX                  1
+
+#define EXCP_RESET                  1
+#define EXCP_INT(n)                 (EXCP_RESET + (n) + 1)
+
+#define PHYS_ADDR_MASK              0xfff00000
+#define PHYS_CODE_BASE              0x00000000
+#define PHYS_DATA_BASE              0x00800000
+
+typedef struct CPUAVRState CPUAVRState;
+
+struct CPUAVRState {
+    uint32_t        pc;     /*  22 bits         */
+
+    uint32_t        sregC;  /*   1 bits         */
+    uint32_t        sregZ;  /*   1 bits         */
+    uint32_t        sregN;  /*   1 bits         */
+    uint32_t        sregV;  /*   1 bits         */
+    uint32_t        sregS;  /*   1 bits         */
+    uint32_t        sregH;  /*   1 bits         */
+    uint32_t        sregT;  /*   1 bits         */
+    uint32_t        sregI;  /*   1 bits         */
+
+    uint32_t        rampD;  /*   8 bits         */
+    uint32_t        rampX;  /*   8 bits         */
+    uint32_t        rampY;  /*   8 bits         */
+    uint32_t        rampZ;  /*   8 bits         */
+
+    uint32_t        io[64]; /*   8 bits each    */
+    uint32_t        r[32];  /*   8 bits each    */
+    uint32_t        eind;   /*   8 bits         */
+    uint32_t        sp;     /*   8 bits         */
+
+
+    uint64_t        intsrc; /*  interrupt sources   */
+
+    /* Those resources are used only in QEMU core */
+    CPU_COMMON
+};
+
+#define cpu_list            avr_cpu_list
+#define cpu_exec            cpu_avr_exec
+#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  0;
+}
+
+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);
+
+#ifndef CONFIG_USER_ONLY
+QEMU_NORETURN void  avr_cpu_unassigned_access(
+                                CPUState           *cpu,
+                                hwaddr              addr,
+                                bool                is_write,
+                                bool                is_exec,
+                                int                 unused,
+                                unsigned            size);
+#endif
+
+static inline void  cpu_get_tb_cpu_state(
+                                CPUAVRState        *env,
+                                target_ulong       *pc,
+                                target_ulong       *cs_base,
+                                uint32_t           *pflags)
+{
+    *pc         = env->pc * 2;
+    *cs_base    = 0;
+    *pflags     = 0;
+}
+
+static inline int   cpu_interrupts_enabled(
+                                CPUAVRState        *env1)
+{
+    return  env1->sregI != 0;
+}
+
+#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..5923f49
--- /dev/null
+++ b/target-avr/gdbstub.c
@@ -0,0 +1,105 @@
+/*
+ * 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    = 0;
+
+        sreg    =   (env->sregC & 0x01) << 0
+                |   (env->sregZ & 0x01) << 1
+                |   (env->sregN & 0x01) << 2
+                |   (env->sregV & 0x01) << 3
+                |   (env->sregS & 0x01) << 4
+                |   (env->sregH & 0x01) << 5
+                |   (env->sregT & 0x01) << 6
+                |   (env->sregI & 0x01) << 7;
+        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 * 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;
+    uint16_t        tmp = ldl_p(mem_buf);
+
+    /*  R */
+    if (n < 32) {
+        env->r[n]   = tmp;
+    }
+
+    /*  SREG */
+    if (n == 32) {
+        env->sregC  = (tmp >> 0) & 0x01;
+        env->sregZ  = (tmp >> 1) & 0x01;
+        env->sregN  = (tmp >> 2) & 0x01;
+        env->sregV  = (tmp >> 3) & 0x01;
+        env->sregS  = (tmp >> 4) & 0x01;
+        env->sregH  = (tmp >> 5) & 0x01;
+        env->sregT  = (tmp >> 6) & 0x01;
+        env->sregI  = (tmp >> 7) & 0x01;
+    }
+
+    /*  SP */
+    if (n == 33) {
+        env->sp = tmp;
+        return  2;
+    }
+
+    /*  PC */
+    if (n == 34) {
+        env->pc = tmp / 2;
+        return  4;
+    }
+
+    return 1;
+}
diff --git a/target-avr/helper.c b/target-avr/helper.c
new file mode 100644
index 0000000..aec37af
--- /dev/null
+++ b/target-avr/helper.c
@@ -0,0 +1,105 @@
+/*
+ * 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)
+{
+    return  false;
+}
+
+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)
+{
+    cs->exception_index = EXCP_DEBUG;
+    cpu_dump_state(cs, stderr, fprintf, 0);
+    return 1;
+}
+
+void                tlb_fill(
+                                CPUState           *cs,
+                                target_ulong        vaddr,
+                                int                 is_write,
+                                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 == CODE_INDEX) {
+        paddr   = PHYS_CODE_BASE + vaddr;
+        prot    = PAGE_READ | PAGE_EXEC;
+    } else {
+        paddr   = PHYS_DATA_BASE + vaddr;
+        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..017e076
--- /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..98d44e9
--- /dev/null
+++ b/target-avr/machine.c
@@ -0,0 +1,54 @@
+/*
+ * 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 "machine.h"
+
+const VMStateDescription vmstate_avr_cpu = {
+    .name               = "cpu",
+    .version_id         = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(r, CPUAVRState, 32),
+
+        VMSTATE_UINT32(sregC,   CPUAVRState),
+        VMSTATE_UINT32(sregZ,   CPUAVRState),
+        VMSTATE_UINT32(sregN,   CPUAVRState),
+        VMSTATE_UINT32(sregV,   CPUAVRState),
+        VMSTATE_UINT32(sregS,   CPUAVRState),
+        VMSTATE_UINT32(sregH,   CPUAVRState),
+        VMSTATE_UINT32(sregT,   CPUAVRState),
+        VMSTATE_UINT32(sregI,   CPUAVRState),
+
+        VMSTATE_UINT32(rampD,   CPUAVRState),
+        VMSTATE_UINT32(rampX,   CPUAVRState),
+        VMSTATE_UINT32(rampY,   CPUAVRState),
+        VMSTATE_UINT32(rampZ,   CPUAVRState),
+
+        VMSTATE_UINT32(eind,    CPUAVRState),
+        VMSTATE_UINT32(sp,      CPUAVRState),
+        VMSTATE_UINT32(pc,      CPUAVRState),
+
+        VMSTATE_END_OF_LIST()
+    }
+};
diff --git a/target-avr/machine.h b/target-avr/machine.h
new file mode 100644
index 0000000..4cc8d6b
--- /dev/null
+++ b/target-avr/machine.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>
+ */
+
+extern const VMStateDescription vmstate_avr_cpu;
diff --git a/target-avr/translate.c b/target-avr/translate.c
new file mode 100644
index 0000000..e98aaef
--- /dev/null
+++ b/target-avr/translate.c
@@ -0,0 +1,300 @@
+/*
+ *  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 "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"
+
+typedef struct DisasContext DisasContext;
+typedef struct InstInfo     InstInfo;
+
+/*This is the state at translation time.  */
+struct DisasContext {
+    struct TranslationBlock    *tb;
+
+    /*Routine used to access memory */
+    int                         memidx;
+    int                         bstate;
+    int                         singlestep;
+};
+
+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           */
+};
+
+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_io[64];
+static TCGv     cpu_r[32];
+static TCGv     cpu_eind;
+static 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),    "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 < 64; i++) {
+        char    name[16];
+
+        sprintf(name, "io[%d]", i);
+
+        cpu_io[i]   = tcg_global_mem_new_i32(cpu_env,   offsetof(CPUAVRState, io[i]),  name);
+    }
+    for (i = 0; i < 32; i++) {
+        char    name[16];
+
+        sprintf(name, "r[%d]", i);
+
+        cpu_r[i]    = tcg_global_mem_new_i32(cpu_env,   offsetof(CPUAVRState, r[i]),    name);
+    }
+
+    done_init = 1;
+}
+
+static inline void  gen_goto_tb(CPUAVRState        *env,
+                                DisasContext       *ctx,
+                                int                 n,
+                                target_ulong        dest)
+{
+    TranslationBlock   *tb;
+
+    tb      = ctx->tb;
+
+    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)
+        &&  (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);
+
+        if (ctx->singlestep) {
+            gen_helper_debug(cpu_env);
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+/*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    */
+    cpc = pc_start;
+    npc = cpc + 1;
+    do {
+        /*  translate current instruction   */
+        tcg_gen_insn_start(cpc);
+        num_insns++;
+
+        /*  just skip to next instruction   */
+        cpc++;
+        npc++;
+        ctx.bstate  = BS_NONE;
+
+        if (unlikely(cpu_breakpoint_test(cs, cpc * 2, BP_ANY))) {
+            tcg_gen_movi_i32(cpu_pc, cpc);
+            gen_helper_debug(cpu_env);
+            ctx.bstate  = BS_EXCP;
+            /*The address covered by the breakpoint must be included in
+               [tb->pc, tb->pc + tb->size) in order to for it to be
+               properly cleared -- thus we increment the PC here so that
+               the logic setting tb->size below does the right thing.  */
+            goto done_generating;
+        }
+
+        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 */
+        }
+    } 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 = 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;
+
+    cpu_fprintf(f, "\n");
+    cpu_fprintf(f, "PC:    %06x\n", env->pc);
+    cpu_fprintf(f, "SP:      %04x\n", env->sp);
+    cpu_fprintf(f, "rampX:     %02x\n", env->rampX);
+    cpu_fprintf(f, "rampY:     %02x\n", env->rampY);
+    cpu_fprintf(f, "rampZ:     %02x\n", env->rampZ);
+    cpu_fprintf(f, "rampD:     %02x\n", env->rampD);
+    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, "         [ I T H S V N Z C ]\n");
+    cpu_fprintf(f, "SREG:    [ %d %d %d %d %d %d %d %d ]\n",
+                        env->sregI,
+                        env->sregT,
+                        env->sregH,
+                        env->sregS,
+                        env->sregV,
+                        env->sregN,
+                        env->sregZ,
+                        env->sregC);
+
+    cpu_fprintf(f, "\n");
+    for (int 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");
+    for (int i = 0; i < ARRAY_SIZE(env->io); i++) {
+        cpu_fprintf(f, "IO[%02d]: %02x   ", i, env->io[i]);
+
+        if ((i % 8) == 7) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+}
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH 2/9] adding AVR CPU features/flavors
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
@ 2016-05-30  1:23 ` Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 3/9] adding a sample AVR board Michael Rolnik
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-avr/cpu.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 target-avr/cpu.h |  59 ++++++++++
 2 files changed, 383 insertions(+), 2 deletions(-)

diff --git a/target-avr/cpu.c b/target-avr/cpu.c
index ff26018..9be0a1d 100644
--- a/target-avr/cpu.c
+++ b/target-avr/cpu.c
@@ -31,7 +31,7 @@ static void         avr_cpu_set_pc(
 {
     AVRCPU   *cpu = AVR_CPU(cs);
 
-    cpu->env.pc = value / 2;    /*  internaly PC points to words, not bytes */
+    cpu->env.pc = value / 2;    /*  internally PC points to words   */
 }
 
 static bool         avr_cpu_has_work(
@@ -52,7 +52,7 @@ static void         avr_cpu_synchronize_from_tb(
     AVRCPU      *cpu = AVR_CPU(cs);
     CPUAVRState *env = &cpu->env;
 
-    env->pc     = tb->pc / 2;
+    env->pc     = tb->pc / 2;   /*  internally PC points to words   */
 }
 
 static void         avr_cpu_reset(
@@ -61,12 +61,14 @@ static void         avr_cpu_reset(
     AVRCPU         *cpu = AVR_CPU(s);
     AVRCPUClass    *mcc = AVR_CPU_GET_CLASS(cpu);
     CPUAVRState    *env = &cpu->env;
+    uint32_t        features    = env->features;
 
     mcc->parent_reset(s);
 
     memset(env, 0, sizeof(CPUAVRState));
     env->pc         = 0;
     env->sregI      = 1;
+    env->features   = features;
 
     tlb_flush(s, 1);
 }
@@ -206,6 +208,311 @@ static void         avr_cpu_class_init(
                             = 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);
+}
+
 static void         avr_any_initfn(
                                 Object             *obj)
 {
@@ -218,6 +525,21 @@ typedef struct AVRCPUInfo {
 } 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},
     {   .name = "any",      .initfn = avr_any_initfn },
 };
 
diff --git a/target-avr/cpu.h b/target-avr/cpu.h
index 3692329..2b67e89 100644
--- a/target-avr/cpu.h
+++ b/target-avr/cpu.h
@@ -47,6 +47,43 @@
 #define PHYS_CODE_BASE              0x00000000
 #define PHYS_DATA_BASE              0x00800000
 
+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 {
@@ -74,10 +111,32 @@ 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 & (1UL << feature)) != 0;
+}
+
+static inline void  avr_set_feature(
+                                CPUAVRState        *env,
+                                int                 feature)
+{
+    env->features   |= (1Ul << feature);
+}
+static inline void  avr_del_feature(
+                                CPUAVRState        *env,
+                                int                 feature)
+{
+    env->features   &= ~(1Ul << feature);
+}
+
 #define cpu_list            avr_cpu_list
 #define cpu_exec            cpu_avr_exec
 #define cpu_signal_handler  cpu_avr_signal_handler
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH 3/9] adding a sample AVR board
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 2/9] adding AVR CPU features/flavors Michael Rolnik
@ 2016-05-30  1:23 ` Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 4/9] adding instructions encodings for LE and BE compilers Michael Rolnik
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 hw/Makefile.objs     |   1 +
 hw/avr/Makefile.objs |   1 +
 hw/avr/sample-io.c   | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/avr/sample.c      | 120 +++++++++++++++++++++++++
 4 files changed, 368 insertions(+)
 create mode 100644 hw/avr/Makefile.objs
 create mode 100644 hw/avr/sample-io.c
 create mode 100644 hw/avr/sample.c

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 4a07ed4..262ca15 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -33,6 +33,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
 devices-dirs-$(CONFIG_SOFTMMU) += xen/
 devices-dirs-$(CONFIG_MEM_HOTPLUG) += mem/
 devices-dirs-$(CONFIG_SMBIOS) += smbios/
+devices-dirs-$(CONFIG_SOFTMMU) += avr/
 devices-dirs-y += core/
 common-obj-y += $(devices-dirs-y)
 obj-y += $(devices-dirs-y)
diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
new file mode 100644
index 0000000..9f6be2f
--- /dev/null
+++ b/hw/avr/Makefile.objs
@@ -0,0 +1 @@
+obj-y   += sample.o sample-io.o
diff --git a/hw/avr/sample-io.c b/hw/avr/sample-io.c
new file mode 100644
index 0000000..133c72f
--- /dev/null
+++ b/hw/avr/sample-io.c
@@ -0,0 +1,246 @@
+/*
+ *  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 "qemu-common.h"
+#include "cpu.h"
+#include "include/hw/sysbus.h"
+
+#define TYPE_SAMPLEIO   "SampleIO"
+#define SAMPLEIO(obj)   OBJECT_CHECK(SAMPLEIOState, (obj), TYPE_SAMPLEIO)
+
+#ifndef DEBUG_SAMPLEIO
+#define DEBUG_SAMPLEIO 1
+#endif
+
+#define DPRINTF(fmt, args...)                                                 \
+    do {                                                                      \
+        if (DEBUG_SAMPLEIO) {                                                 \
+            fprintf(stderr, "[%s]%s: " fmt , TYPE_SAMPLEIO, __func__, ##args);\
+        }                                                                     \
+    }                                                                         \
+    while (0)
+
+#define AVR_IO_CPU_REGS_SIZE    0x0020
+#define AVR_IO_CPU_IO_SIZE      0x0040
+#define AVR_IO_EXTERN_IO_SIZE   0x00a0
+#define AVR_IO_SIZE             (AVR_IO_CPU_REGS_SIZE   \
+                                + AVR_IO_CPU_IO_SIZE    \
+                                + AVR_IO_EXTERN_IO_SIZE)
+
+#define AVR_IO_CPU_REGS_BASE    0x0000
+#define AVR_IO_CPU_IO_BASE      (AVR_IO_CPU_REGS_BASE   \
+                                + AVR_IO_CPU_REGS_SIZE)
+#define AVR_IO_EXTERN_IO_BASE   (AVR_IO_CPU_IO_BASE     \
+                                + AVR_IO_CPU_IO_SIZE)
+
+
+typedef struct SAMPLEIOState {
+    SysBusDevice    parent;
+
+    MemoryRegion    iomem;
+
+    AVRCPU         *cpu;
+
+    uint8_t         io[0x40];
+    uint8_t         exio[0xa0];
+} SAMPLEIOState;
+
+static uint64_t sample_io_read(
+                                void                   *opaque,
+                                hwaddr                  offset,
+                                unsigned                size);
+static void     sample_io_write(void                   *opaque,
+                                hwaddr                  offset,
+                                uint64_t                value,
+                                unsigned                size);
+static int      sample_io_init(
+                                DeviceState            *sbd);
+static void     sample_io_class_init(
+                                ObjectClass            *klass,
+                                void                   *data);
+static void     sample_io_register_types(void);
+
+static void     write_Rx(
+                                CPUAVRState            *env,
+                                int                     inst,
+                                uint8_t                 data);
+static uint8_t  read_Rx(
+                                CPUAVRState            *env,
+                                int                     inst);
+
+static const
+MemoryRegionOps     sample_io_ops = {
+    .read       = sample_io_read,
+    .write      = sample_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static
+Property            sample_io_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+static const
+VMStateDescription  sample_io_vmstate = {
+    .name               = TYPE_SAMPLEIO,
+    .version_id         = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[])
+    {
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void        write_Rx(
+                                CPUAVRState            *env,
+                                int                     inst,
+                                uint8_t                 data)
+{
+    env->r[inst]  = data;
+}
+uint8_t     read_Rx(
+                                CPUAVRState            *env,
+                                int                     inst)
+{
+    return  env->r[inst];
+}
+
+static
+void    sample_io_reset(DeviceState *dev)
+{
+    DPRINTF("\n");
+}
+
+static
+uint64_t    sample_io_read(
+                                void                   *opaque,
+                                hwaddr                  offset,
+                                unsigned                size)
+{
+    SAMPLEIOState  *s   = SAMPLEIO(opaque);
+    AVRCPU         *cpu = s->cpu;
+    CPUAVRState    *env = &cpu->env;
+    uint64_t        res = 0;
+
+    assert(size == 1);
+
+    if (AVR_IO_CPU_REGS_BASE <= offset
+        && offset < (AVR_IO_CPU_REGS_BASE + AVR_IO_CPU_REGS_SIZE)) {
+        res = read_Rx(env, offset - AVR_IO_CPU_REGS_BASE);
+    } else if (AVR_IO_CPU_IO_BASE <= offset
+            && offset < (AVR_IO_CPU_IO_BASE + AVR_IO_CPU_IO_SIZE)) {
+        /*  TODO: do IO related stuff here  */
+        res = s->io[offset - AVR_IO_CPU_IO_BASE];
+    } else if (AVR_IO_EXTERN_IO_BASE <= offset
+            && offset < (AVR_IO_EXTERN_IO_BASE + AVR_IO_EXTERN_IO_SIZE)) {
+        /*  TODO: do IO related stuff here  */
+        res = s->io[offset - AVR_IO_EXTERN_IO_BASE];
+    } else {
+        g_assert_not_reached();
+    }
+
+    return  res;
+}
+
+static
+void        sample_io_write(
+                                void                   *opaque,
+                                hwaddr                  offset,
+                                uint64_t                value,
+                                unsigned                size)
+{
+    SAMPLEIOState  *s   = SAMPLEIO(opaque);
+    AVRCPU         *cpu = s->cpu;
+    CPUAVRState    *env = &cpu->env;
+
+    assert(size == 1);
+
+    if (AVR_IO_CPU_REGS_BASE <= offset
+        && offset < (AVR_IO_CPU_REGS_BASE + AVR_IO_CPU_REGS_SIZE)) {
+        return  write_Rx(env, offset - AVR_IO_CPU_REGS_BASE, value);
+    } else if (AVR_IO_CPU_IO_BASE <= offset
+            && offset < (AVR_IO_CPU_IO_BASE + AVR_IO_CPU_IO_SIZE)) {
+        /*  TODO: do IO related stuff here  */
+        s->io[offset - AVR_IO_CPU_IO_BASE]  = value;
+    } else if (AVR_IO_EXTERN_IO_BASE <= offset
+            && offset < (AVR_IO_EXTERN_IO_BASE + AVR_IO_EXTERN_IO_SIZE)) {
+        /*  TODO: do IO related stuff here  */
+        s->io[offset - AVR_IO_EXTERN_IO_BASE]   = value;
+    } else {
+        g_assert_not_reached();
+    }
+}
+
+static
+int         sample_io_init(
+                                DeviceState            *dev)
+{
+    SysBusDevice   *sbd = SYS_BUS_DEVICE(dev);
+    SAMPLEIOState  *s   = SAMPLEIO(dev);
+
+    assert(AVR_IO_SIZE <= TARGET_PAGE_SIZE);
+
+    s->cpu  = AVR_CPU(qemu_get_cpu(0));
+
+    memory_region_init_io(
+            &s->iomem,
+            OBJECT(s),
+            &sample_io_ops,
+            s,
+            TYPE_SAMPLEIO,
+            AVR_IO_SIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    return  0;
+}
+
+static
+void        sample_io_class_init(
+                                ObjectClass            *klass,
+                                void                   *data)
+{
+    DeviceClass    *dc  = DEVICE_CLASS(klass);
+
+    DPRINTF("\n");
+
+    dc->init    = sample_io_init;
+    dc->reset   = sample_io_reset;
+    dc->desc    = "at90 io regs";
+    dc->vmsd    = &sample_io_vmstate;
+    dc->props   = sample_io_properties;
+}
+
+static const
+TypeInfo    sample_io_info = {
+    .name           = TYPE_SAMPLEIO,
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(SAMPLEIOState),
+    .class_init     = sample_io_class_init,
+};
+
+static
+void        sample_io_register_types(void)
+{
+    DPRINTF("\n");
+    type_register_static(&sample_io_info);
+}
+
+type_init(sample_io_register_types)
diff --git a/hw/avr/sample.c b/hw/avr/sample.c
new file mode 100644
index 0000000..d8b9d5c
--- /dev/null
+++ b/hw/avr/sample.c
@@ -0,0 +1,120 @@
+/*
+ * 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 "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_IOREG     0x00000000
+#define VIRT_BASE_ISRAM     0x00000100
+#define VIRT_BASE_EXMEM     0x00001100
+#define VIRT_BASE_EEPROM    0x00000000
+
+#define VIRT_BASE_BOOT      0x0001e000
+#define PHYS_BASE_BOOT      (PHYS_BASE_FLASH + VIRT_BASE_BOOT)
+
+#define SIZE_FLASH          0x00020000
+#define SIZE_IOREG          0x00000100
+#define SIZE_ISRAM          0x00001000
+#define SIZE_EXMEM          0x00010000
+#define SIZE_EEPROM         0x00001000
+
+#define PHYS_BASE_FLASH     (PHYS_CODE_BASE)
+#define PHYS_BASE_IOREG     (PHYS_DATA_BASE)
+#define PHYS_BASE_ISRAM     (PHYS_BASE_IOREG + SIZE_IOREG)
+#define PHYS_BASE_EXMEM     (PHYS_BASE_ISRAM + SIZE_ISRAM)
+#define PHYS_BASE_EEPROM    (PHYS_BASE_EXMEM + SIZE_EXMEM)
+
+
+static
+void    sample_init(MachineState *machine)
+{
+    MemoryRegion   *address_space_mem   = get_system_memory();
+
+    MemoryRegion   *flash;
+    MemoryRegion   *isram;
+    MemoryRegion   *exmem;
+
+    AVRCPU         *cpu_avr;
+    DeviceState    *io;
+    SysBusDevice   *bus;
+
+    flash   = g_new(MemoryRegion, 1);
+    isram   = g_new(MemoryRegion, 1);
+    exmem   = g_new(MemoryRegion, 1);
+
+    cpu_avr = cpu_avr_init("avr5");
+    io      = qdev_create(NULL, "SampleIO");
+    bus     = SYS_BUS_DEVICE(io);
+    qdev_init_nofail(io);
+
+    memory_region_init_ram(flash, NULL, "flash", SIZE_FLASH, &error_fatal);
+    memory_region_init_ram(isram, NULL, "isram", SIZE_ISRAM, &error_fatal);
+    memory_region_init_ram(exmem, NULL, "exmem", SIZE_EXMEM, &error_fatal);
+
+    memory_region_add_subregion(address_space_mem, PHYS_BASE_FLASH, flash);
+    memory_region_add_subregion(address_space_mem, PHYS_BASE_ISRAM, isram);
+    memory_region_add_subregion(address_space_mem, PHYS_BASE_EXMEM, exmem);
+
+    vmstate_register_ram_global(flash);
+    vmstate_register_ram_global(isram);
+    vmstate_register_ram_global(exmem);
+
+    memory_region_set_readonly(flash, true);
+
+    char const *firmware    = NULL;
+    char const *filename;
+
+    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);
+
+    sysbus_mmio_map(bus, 0, PHYS_BASE_IOREG);
+}
+
+static
+void    sample_machine_init(MachineClass *mc)
+{
+    mc->desc        = "sample";
+    mc->init        = sample_init;
+    mc->is_default  = 1;
+}
+
+DEFINE_MACHINE("sample",    sample_machine_init)
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH 4/9] adding instructions encodings for LE and BE compilers.
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 2/9] adding AVR CPU features/flavors Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 3/9] adding a sample AVR board Michael Rolnik
@ 2016-05-30  1:23 ` Michael Rolnik
  2016-06-02  6:32   ` Richard Henderson
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 5/9] adding AVR interrupt handling Michael Rolnik
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

    I am aware of bad portability of bit fields as compilers
    for LE and BE hosts lists bit fields in different order
    However they won't "parse" in target memory but a data prepared by me

Signed-off-by: Michael Rolnik <mrolnik@gmail.co>
---
 target-avr/inst-be.h | 1018 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-avr/inst-le.h | 1018 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 2036 insertions(+)
 create mode 100644 target-avr/inst-be.h
 create mode 100644 target-avr/inst-le.h

diff --git a/target-avr/inst-be.h b/target-avr/inst-be.h
new file mode 100644
index 0000000..99897c0
--- /dev/null
+++ b/target-avr/inst-be.h
@@ -0,0 +1,1018 @@
+/*
+ * 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>
+ */
+
+
+typedef struct DisasContext    DisasContext;
+typedef struct CPUAVRState     CPUAVRState;
+
+typedef union avr_opcode_NOP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 0000000000000000 */
+    };
+} avr_opcode_NOP_t;
+int     avr_translate_NOP(CPUAVRState *env, DisasContext *ctx, avr_opcode_NOP_t const *inst);
+
+typedef union avr_opcode_MOVW_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 00000001 */
+        uint16_t    Rd:4;
+        uint16_t    Rr:4;
+    };
+} avr_opcode_MOVW_t;
+int     avr_translate_MOVW(CPUAVRState *env, DisasContext *ctx, avr_opcode_MOVW_t const *inst);
+
+typedef union avr_opcode_MULS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 00000010 */
+        uint16_t    Rd:4;
+        uint16_t    Rr:4;
+    };
+} avr_opcode_MULS_t;
+int     avr_translate_MULS(CPUAVRState *env, DisasContext *ctx, avr_opcode_MULS_t const *inst);
+
+typedef union avr_opcode_MULSU_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:9; /* 000000110 */
+        uint16_t    Rd:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rr:3;
+    };
+} avr_opcode_MULSU_t;
+int     avr_translate_MULSU(CPUAVRState *env, DisasContext *ctx, avr_opcode_MULSU_t const *inst);
+
+typedef union avr_opcode_FMUL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:9; /* 000000110 */
+        uint16_t    Rd:3;
+        uint16_t:1; /* 1 */
+        uint16_t    Rr:3;
+    };
+} avr_opcode_FMUL_t;
+int     avr_translate_FMUL(CPUAVRState *env, DisasContext *ctx, avr_opcode_FMUL_t const *inst);
+
+typedef union avr_opcode_FMULS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:9; /* 000000111 */
+        uint16_t    Rd:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rr:3;
+    };
+} avr_opcode_FMULS_t;
+int     avr_translate_FMULS(CPUAVRState *env, DisasContext *ctx, avr_opcode_FMULS_t const *inst);
+
+typedef union avr_opcode_FMULSU_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:9; /* 000000111 */
+        uint16_t    Rd:3;
+        uint16_t:1; /* 1 */
+        uint16_t    Rr:3;
+    };
+} avr_opcode_FMULSU_t;
+int     avr_translate_FMULSU(CPUAVRState *env, DisasContext *ctx, avr_opcode_FMULSU_t const *inst);
+
+typedef union avr_opcode_CPC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 000001 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_CPC_t;
+int     avr_translate_CPC(CPUAVRState *env, DisasContext *ctx, avr_opcode_CPC_t const *inst);
+
+typedef union avr_opcode_SBC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 000010 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_SBC_t;
+int     avr_translate_SBC(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBC_t const *inst);
+
+typedef union avr_opcode_ADD_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 000011 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_ADD_t;
+int     avr_translate_ADD(CPUAVRState *env, DisasContext *ctx, avr_opcode_ADD_t const *inst);
+
+typedef union avr_opcode_AND_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 001000 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_AND_t;
+int     avr_translate_AND(CPUAVRState *env, DisasContext *ctx, avr_opcode_AND_t const *inst);
+
+typedef union avr_opcode_EOR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 001001 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_EOR_t;
+int     avr_translate_EOR(CPUAVRState *env, DisasContext *ctx, avr_opcode_EOR_t const *inst);
+
+typedef union avr_opcode_OR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 001010 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_OR_t;
+int     avr_translate_OR(CPUAVRState *env, DisasContext *ctx, avr_opcode_OR_t const *inst);
+
+typedef union avr_opcode_MOV_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 001011 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_MOV_t;
+int     avr_translate_MOV(CPUAVRState *env, DisasContext *ctx, avr_opcode_MOV_t const *inst);
+
+typedef union avr_opcode_CPSE_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 000100 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_CPSE_t;
+int     avr_translate_CPSE(CPUAVRState *env, DisasContext *ctx, avr_opcode_CPSE_t const *inst);
+
+typedef union avr_opcode_CP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 000101 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_CP_t;
+int     avr_translate_CP(CPUAVRState *env, DisasContext *ctx, avr_opcode_CP_t const *inst);
+
+typedef union avr_opcode_SUB_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 000110 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_SUB_t;
+int     avr_translate_SUB(CPUAVRState *env, DisasContext *ctx, avr_opcode_SUB_t const *inst);
+
+typedef union avr_opcode_ADC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 000111 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_ADC_t;
+int     avr_translate_ADC(CPUAVRState *env, DisasContext *ctx, avr_opcode_ADC_t const *inst);
+
+typedef union avr_opcode_CPI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0011 */
+        uint16_t    hImm:4;
+        uint16_t    Rd:4;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_CPI_t;
+int     avr_translate_CPI(CPUAVRState *env, DisasContext *ctx, avr_opcode_CPI_t const *inst);
+
+typedef union avr_opcode_SBCI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0100 */
+        uint16_t    hImm:4;
+        uint16_t    Rd:4;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_SBCI_t;
+int     avr_translate_SBCI(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBCI_t const *inst);
+
+typedef union avr_opcode_ORI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0110 */
+        uint16_t    hImm:4;
+        uint16_t    Rd:4;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_ORI_t;
+int     avr_translate_ORI(CPUAVRState *env, DisasContext *ctx, avr_opcode_ORI_t const *inst);
+
+typedef union avr_opcode_SUBI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0101 */
+        uint16_t    hImm:4;
+        uint16_t    Rd:4;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_SUBI_t;
+int     avr_translate_SUBI(CPUAVRState *env, DisasContext *ctx, avr_opcode_SUBI_t const *inst);
+
+typedef union avr_opcode_ANDI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0111 */
+        uint16_t    hImm:4;
+        uint16_t    Rd:4;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_ANDI_t;
+int     avr_translate_ANDI(CPUAVRState *env, DisasContext *ctx, avr_opcode_ANDI_t const *inst);
+
+typedef union avr_opcode_LDDZ_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:2; /* 10 */
+        uint16_t    hImm:1;
+        uint16_t:1; /* 0 */
+        uint16_t    mImm:2;
+        uint16_t:1; /* 0 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 0 */
+        uint16_t    lImm:3;
+    };
+} avr_opcode_LDDZ_t;
+int     avr_translate_LDDZ(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDDZ_t const *inst);
+
+typedef union avr_opcode_LDDY_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:2; /* 10 */
+        uint16_t    hImm:1;
+        uint16_t:1; /* 0 */
+        uint16_t    mImm:2;
+        uint16_t:1; /* 0 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 1 */
+        uint16_t    lImm:3;
+    };
+} avr_opcode_LDDY_t;
+int     avr_translate_LDDY(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDDY_t const *inst);
+
+typedef union avr_opcode_STDZ_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:2; /* 10 */
+        uint16_t    hImm:1;
+        uint16_t:1; /* 0 */
+        uint16_t    mImm:2;
+        uint16_t:1; /* 1 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 0 */
+        uint16_t    lImm:3;
+    };
+} avr_opcode_STDZ_t;
+int     avr_translate_STDZ(CPUAVRState *env, DisasContext *ctx, avr_opcode_STDZ_t const *inst);
+
+typedef union avr_opcode_STDY_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:2; /* 10 */
+        uint16_t    hImm:1;
+        uint16_t:1; /* 0 */
+        uint16_t    mImm:2;
+        uint16_t:1; /* 1 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 1 */
+        uint16_t    lImm:3;
+    };
+} avr_opcode_STDY_t;
+int     avr_translate_STDY(CPUAVRState *env, DisasContext *ctx, avr_opcode_STDY_t const *inst);
+
+typedef union avr_opcode_LDS_u {
+    uint32_t    opcode;
+    struct {
+        uint32_t:7; /* 1001000 */
+        uint32_t    Rd:5;
+        uint32_t:4; /* 0000 */
+        uint32_t    Imm:16;
+    };
+} avr_opcode_LDS_t;
+int     avr_translate_LDS(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDS_t const *inst);
+
+typedef union avr_opcode_LDZ2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0001 */
+    };
+} avr_opcode_LDZ2_t;
+int     avr_translate_LDZ2(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDZ2_t const *inst);
+
+typedef union avr_opcode_LDZ3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0010 */
+    };
+} avr_opcode_LDZ3_t;
+int     avr_translate_LDZ3(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDZ3_t const *inst);
+
+typedef union avr_opcode_LPM2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0100 */
+    };
+} avr_opcode_LPM2_t;
+int     avr_translate_LPM2(CPUAVRState *env, DisasContext *ctx, avr_opcode_LPM2_t const *inst);
+
+typedef union avr_opcode_LPMX_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0101 */
+    };
+} avr_opcode_LPMX_t;
+int     avr_translate_LPMX(CPUAVRState *env, DisasContext *ctx, avr_opcode_LPMX_t const *inst);
+
+typedef union avr_opcode_ELPM2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0110 */
+    };
+} avr_opcode_ELPM2_t;
+int     avr_translate_ELPM2(CPUAVRState *env, DisasContext *ctx, avr_opcode_ELPM2_t const *inst);
+
+typedef union avr_opcode_ELPMX_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0111 */
+    };
+} avr_opcode_ELPMX_t;
+int     avr_translate_ELPMX(CPUAVRState *env, DisasContext *ctx, avr_opcode_ELPMX_t const *inst);
+
+typedef union avr_opcode_LDY2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1001 */
+    };
+} avr_opcode_LDY2_t;
+int     avr_translate_LDY2(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDY2_t const *inst);
+
+typedef union avr_opcode_LDY3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1010 */
+    };
+} avr_opcode_LDY3_t;
+int     avr_translate_LDY3(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDY3_t const *inst);
+
+typedef union avr_opcode_LDX1_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1100 */
+    };
+} avr_opcode_LDX1_t;
+int     avr_translate_LDX1(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDX1_t const *inst);
+
+typedef union avr_opcode_LDX2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1101 */
+    };
+} avr_opcode_LDX2_t;
+int     avr_translate_LDX2(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDX2_t const *inst);
+
+typedef union avr_opcode_LDX3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1110 */
+    };
+} avr_opcode_LDX3_t;
+int     avr_translate_LDX3(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDX3_t const *inst);
+
+typedef union avr_opcode_POP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001000 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1111 */
+    };
+} avr_opcode_POP_t;
+int     avr_translate_POP(CPUAVRState *env, DisasContext *ctx, avr_opcode_POP_t const *inst);
+
+typedef union avr_opcode_STS_u {
+    uint32_t    opcode;
+    struct {
+        uint32_t:7; /* 1001001 */
+        uint32_t    Rd:5;
+        uint32_t:4; /* 0000 */
+        uint32_t    Imm:16;
+    };
+} avr_opcode_STS_t;
+int     avr_translate_STS(CPUAVRState *env, DisasContext *ctx, avr_opcode_STS_t const *inst);
+
+typedef union avr_opcode_STZ2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0001 */
+    };
+} avr_opcode_STZ2_t;
+int     avr_translate_STZ2(CPUAVRState *env, DisasContext *ctx, avr_opcode_STZ2_t const *inst);
+
+typedef union avr_opcode_STZ3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0010 */
+    };
+} avr_opcode_STZ3_t;
+int     avr_translate_STZ3(CPUAVRState *env, DisasContext *ctx, avr_opcode_STZ3_t const *inst);
+
+typedef union avr_opcode_XCH_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0100 */
+    };
+} avr_opcode_XCH_t;
+int     avr_translate_XCH(CPUAVRState *env, DisasContext *ctx, avr_opcode_XCH_t const *inst);
+
+typedef union avr_opcode_LAS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rr:5;
+        uint16_t:4; /* 0101 */
+    };
+} avr_opcode_LAS_t;
+int     avr_translate_LAS(CPUAVRState *env, DisasContext *ctx, avr_opcode_LAS_t const *inst);
+
+typedef union avr_opcode_LAC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rr:5;
+        uint16_t:4; /* 0110 */
+    };
+} avr_opcode_LAC_t;
+int     avr_translate_LAC(CPUAVRState *env, DisasContext *ctx, avr_opcode_LAC_t const *inst);
+
+typedef union avr_opcode_LAT_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rr:5;
+        uint16_t:4; /* 0111 */
+    };
+} avr_opcode_LAT_t;
+int     avr_translate_LAT(CPUAVRState *env, DisasContext *ctx, avr_opcode_LAT_t const *inst);
+
+typedef union avr_opcode_STY2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1001 */
+    };
+} avr_opcode_STY2_t;
+int     avr_translate_STY2(CPUAVRState *env, DisasContext *ctx, avr_opcode_STY2_t const *inst);
+
+typedef union avr_opcode_STY3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1010 */
+    };
+} avr_opcode_STY3_t;
+int     avr_translate_STY3(CPUAVRState *env, DisasContext *ctx, avr_opcode_STY3_t const *inst);
+
+typedef union avr_opcode_STX1_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rr:5;
+        uint16_t:4; /* 1100 */
+    };
+} avr_opcode_STX1_t;
+int     avr_translate_STX1(CPUAVRState *env, DisasContext *ctx, avr_opcode_STX1_t const *inst);
+
+typedef union avr_opcode_STX2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rr:5;
+        uint16_t:4; /* 1101 */
+    };
+} avr_opcode_STX2_t;
+int     avr_translate_STX2(CPUAVRState *env, DisasContext *ctx, avr_opcode_STX2_t const *inst);
+
+typedef union avr_opcode_STX3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rr:5;
+        uint16_t:4; /* 1110 */
+    };
+} avr_opcode_STX3_t;
+int     avr_translate_STX3(CPUAVRState *env, DisasContext *ctx, avr_opcode_STX3_t const *inst);
+
+typedef union avr_opcode_PUSH_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001001 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1111 */
+    };
+} avr_opcode_PUSH_t;
+int     avr_translate_PUSH(CPUAVRState *env, DisasContext *ctx, avr_opcode_PUSH_t const *inst);
+
+typedef union avr_opcode_COM_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001010 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0000 */
+    };
+} avr_opcode_COM_t;
+int     avr_translate_COM(CPUAVRState *env, DisasContext *ctx, avr_opcode_COM_t const *inst);
+
+typedef union avr_opcode_NEG_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001010 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0001 */
+    };
+} avr_opcode_NEG_t;
+int     avr_translate_NEG(CPUAVRState *env, DisasContext *ctx, avr_opcode_NEG_t const *inst);
+
+typedef union avr_opcode_SWAP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001010 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0010 */
+    };
+} avr_opcode_SWAP_t;
+int     avr_translate_SWAP(CPUAVRState *env, DisasContext *ctx, avr_opcode_SWAP_t const *inst);
+
+typedef union avr_opcode_INC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001010 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0011 */
+    };
+} avr_opcode_INC_t;
+int     avr_translate_INC(CPUAVRState *env, DisasContext *ctx, avr_opcode_INC_t const *inst);
+
+typedef union avr_opcode_ASR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001010 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0101 */
+    };
+} avr_opcode_ASR_t;
+int     avr_translate_ASR(CPUAVRState *env, DisasContext *ctx, avr_opcode_ASR_t const *inst);
+
+typedef union avr_opcode_LSR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001010 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0110 */
+    };
+} avr_opcode_LSR_t;
+int     avr_translate_LSR(CPUAVRState *env, DisasContext *ctx, avr_opcode_LSR_t const *inst);
+
+typedef union avr_opcode_ROR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001010 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 0111 */
+    };
+} avr_opcode_ROR_t;
+int     avr_translate_ROR(CPUAVRState *env, DisasContext *ctx, avr_opcode_ROR_t const *inst);
+
+typedef union avr_opcode_BSET_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:9; /* 100101000 */
+        uint16_t    Bit:3;
+        uint16_t:4; /* 1000 */
+    };
+} avr_opcode_BSET_t;
+int     avr_translate_BSET(CPUAVRState *env, DisasContext *ctx, avr_opcode_BSET_t const *inst);
+
+typedef union avr_opcode_IJMP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010000001001 */
+    };
+} avr_opcode_IJMP_t;
+int     avr_translate_IJMP(CPUAVRState *env, DisasContext *ctx, avr_opcode_IJMP_t const *inst);
+
+typedef union avr_opcode_EIJMP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010000011001 */
+    };
+} avr_opcode_EIJMP_t;
+int     avr_translate_EIJMP(CPUAVRState *env, DisasContext *ctx, avr_opcode_EIJMP_t const *inst);
+
+typedef union avr_opcode_BCLR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:9; /* 100101001 */
+        uint16_t    Bit:3;
+        uint16_t:4; /* 1000 */
+    };
+} avr_opcode_BCLR_t;
+int     avr_translate_BCLR(CPUAVRState *env, DisasContext *ctx, avr_opcode_BCLR_t const *inst);
+
+typedef union avr_opcode_RET_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010100001000 */
+    };
+} avr_opcode_RET_t;
+int     avr_translate_RET(CPUAVRState *env, DisasContext *ctx, avr_opcode_RET_t const *inst);
+
+typedef union avr_opcode_RETI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010100011000 */
+    };
+} avr_opcode_RETI_t;
+int     avr_translate_RETI(CPUAVRState *env, DisasContext *ctx, avr_opcode_RETI_t const *inst);
+
+typedef union avr_opcode_ICALL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010100001001 */
+    };
+} avr_opcode_ICALL_t;
+int     avr_translate_ICALL(CPUAVRState *env, DisasContext *ctx, avr_opcode_ICALL_t const *inst);
+
+typedef union avr_opcode_EICALL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010100011001 */
+    };
+} avr_opcode_EICALL_t;
+int     avr_translate_EICALL(CPUAVRState *env, DisasContext *ctx, avr_opcode_EICALL_t const *inst);
+
+typedef union avr_opcode_SLEEP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010110001000 */
+    };
+} avr_opcode_SLEEP_t;
+int     avr_translate_SLEEP(CPUAVRState *env, DisasContext *ctx, avr_opcode_SLEEP_t const *inst);
+
+typedef union avr_opcode_BREAK_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010110011000 */
+    };
+} avr_opcode_BREAK_t;
+int     avr_translate_BREAK(CPUAVRState *env, DisasContext *ctx, avr_opcode_BREAK_t const *inst);
+
+typedef union avr_opcode_WDR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010110101000 */
+    };
+} avr_opcode_WDR_t;
+int     avr_translate_WDR(CPUAVRState *env, DisasContext *ctx, avr_opcode_WDR_t const *inst);
+
+typedef union avr_opcode_LPM1_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010111001000 */
+    };
+} avr_opcode_LPM1_t;
+int     avr_translate_LPM1(CPUAVRState *env, DisasContext *ctx, avr_opcode_LPM1_t const *inst);
+
+typedef union avr_opcode_ELPM1_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010111011000 */
+    };
+} avr_opcode_ELPM1_t;
+int     avr_translate_ELPM1(CPUAVRState *env, DisasContext *ctx, avr_opcode_ELPM1_t const *inst);
+
+typedef union avr_opcode_SPM_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010111101000 */
+    };
+} avr_opcode_SPM_t;
+int     avr_translate_SPM(CPUAVRState *env, DisasContext *ctx, avr_opcode_SPM_t const *inst);
+
+typedef union avr_opcode_SPMX_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010111111000 */
+    };
+} avr_opcode_SPMX_t;
+int     avr_translate_SPMX(CPUAVRState *env, DisasContext *ctx, avr_opcode_SPMX_t const *inst);
+
+typedef union avr_opcode_DEC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1001010 */
+        uint16_t    Rd:5;
+        uint16_t:4; /* 1010 */
+    };
+} avr_opcode_DEC_t;
+int     avr_translate_DEC(CPUAVRState *env, DisasContext *ctx, avr_opcode_DEC_t const *inst);
+
+typedef union avr_opcode_DES_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 10010100 */
+        uint16_t    Imm:4;
+        uint16_t:4; /* 1011 */
+    };
+} avr_opcode_DES_t;
+int     avr_translate_DES(CPUAVRState *env, DisasContext *ctx, avr_opcode_DES_t const *inst);
+
+typedef union avr_opcode_JMP_u {
+    uint32_t    opcode;
+    struct {
+        uint32_t:7; /* 1001010 */
+        uint32_t    hImm:5;
+        uint32_t:3; /* 110 */
+        uint32_t    lImm:17;
+    };
+} avr_opcode_JMP_t;
+int     avr_translate_JMP(CPUAVRState *env, DisasContext *ctx, avr_opcode_JMP_t const *inst);
+
+typedef union avr_opcode_CALL_u {
+    uint32_t    opcode;
+    struct {
+        uint32_t:7; /* 1001010 */
+        uint32_t    hImm:5;
+        uint32_t:3; /* 111 */
+        uint32_t    lImm:17;
+    };
+} avr_opcode_CALL_t;
+int     avr_translate_CALL(CPUAVRState *env, DisasContext *ctx, avr_opcode_CALL_t const *inst);
+
+typedef union avr_opcode_ADIW_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 10010110 */
+        uint16_t    hImm:2;
+        uint16_t    Rd:2;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_ADIW_t;
+int     avr_translate_ADIW(CPUAVRState *env, DisasContext *ctx, avr_opcode_ADIW_t const *inst);
+
+typedef union avr_opcode_SBIW_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 10010111 */
+        uint16_t    hImm:2;
+        uint16_t    Rd:2;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_SBIW_t;
+int     avr_translate_SBIW(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBIW_t const *inst);
+
+typedef union avr_opcode_CBI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 10011000 */
+        uint16_t    Imm:5;
+        uint16_t    Bit:3;
+    };
+} avr_opcode_CBI_t;
+int     avr_translate_CBI(CPUAVRState *env, DisasContext *ctx, avr_opcode_CBI_t const *inst);
+
+typedef union avr_opcode_SBIC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 10011001 */
+        uint16_t    Imm:5;
+        uint16_t    Bit:3;
+    };
+} avr_opcode_SBIC_t;
+int     avr_translate_SBIC(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBIC_t const *inst);
+
+typedef union avr_opcode_SBI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 10011010 */
+        uint16_t    Imm:5;
+        uint16_t    Bit:3;
+    };
+} avr_opcode_SBI_t;
+int     avr_translate_SBI(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBI_t const *inst);
+
+typedef union avr_opcode_SBIS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:8; /* 10011011 */
+        uint16_t    Imm:5;
+        uint16_t    Bit:3;
+    };
+} avr_opcode_SBIS_t;
+int     avr_translate_SBIS(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBIS_t const *inst);
+
+typedef union avr_opcode_MUL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 100111 */
+        uint16_t    hRr:1;
+        uint16_t    Rd:5;
+        uint16_t    lRr:4;
+    };
+} avr_opcode_MUL_t;
+int     avr_translate_MUL(CPUAVRState *env, DisasContext *ctx, avr_opcode_MUL_t const *inst);
+
+typedef union avr_opcode_IN_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:5; /* 10110 */
+        uint16_t    hImm:2;
+        uint16_t    Rd:5;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_IN_t;
+int     avr_translate_IN(CPUAVRState *env, DisasContext *ctx, avr_opcode_IN_t const *inst);
+
+typedef union avr_opcode_OUT_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:5; /* 10111 */
+        uint16_t    hImm:2;
+        uint16_t    Rd:5;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_OUT_t;
+int     avr_translate_OUT(CPUAVRState *env, DisasContext *ctx, avr_opcode_OUT_t const *inst);
+
+typedef union avr_opcode_RJMP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1100 */
+        uint16_t    Imm:12;
+    };
+} avr_opcode_RJMP_t;
+int     avr_translate_RJMP(CPUAVRState *env, DisasContext *ctx, avr_opcode_RJMP_t const *inst);
+
+typedef union avr_opcode_LDI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1110 */
+        uint16_t    hImm:4;
+        uint16_t    Rd:4;
+        uint16_t    lImm:4;
+    };
+} avr_opcode_LDI_t;
+int     avr_translate_LDI(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDI_t const *inst);
+
+typedef union avr_opcode_RCALL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1101 */
+        uint16_t    Imm:12;
+    };
+} avr_opcode_RCALL_t;
+int     avr_translate_RCALL(CPUAVRState *env, DisasContext *ctx, avr_opcode_RCALL_t const *inst);
+
+typedef union avr_opcode_BRBS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 111100 */
+        uint16_t    Imm:7;
+        uint16_t    Bit:3;
+    };
+} avr_opcode_BRBS_t;
+int     avr_translate_BRBS(CPUAVRState *env, DisasContext *ctx, avr_opcode_BRBS_t const *inst);
+
+typedef union avr_opcode_BRBC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:6; /* 111101 */
+        uint16_t    Imm:7;
+        uint16_t    Bit:3;
+    };
+} avr_opcode_BRBC_t;
+int     avr_translate_BRBC(CPUAVRState *env, DisasContext *ctx, avr_opcode_BRBC_t const *inst);
+
+typedef union avr_opcode_BLD_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1111100 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 0 */
+        uint16_t    Bit:3;
+    };
+} avr_opcode_BLD_t;
+int     avr_translate_BLD(CPUAVRState *env, DisasContext *ctx, avr_opcode_BLD_t const *inst);
+
+typedef union avr_opcode_BST_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1111101 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 0 */
+        uint16_t    Bit:3;
+    };
+} avr_opcode_BST_t;
+int     avr_translate_BST(CPUAVRState *env, DisasContext *ctx, avr_opcode_BST_t const *inst);
+
+typedef union avr_opcode_SBRC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1111110 */
+        uint16_t    Rr:5;
+        uint16_t:1; /* 0 */
+        uint16_t    Bit:3;
+    };
+} avr_opcode_SBRC_t;
+int     avr_translate_SBRC(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBRC_t const *inst);
+
+typedef union avr_opcode_SBRS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:7; /* 1111111 */
+        uint16_t    Rr:5;
+        uint16_t:1; /* 0 */
+        uint16_t    Bit:3;
+    };
+} avr_opcode_SBRS_t;
+int     avr_translate_SBRS(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBRS_t const *inst);
+
diff --git a/target-avr/inst-le.h b/target-avr/inst-le.h
new file mode 100644
index 0000000..d73293f
--- /dev/null
+++ b/target-avr/inst-le.h
@@ -0,0 +1,1018 @@
+/*
+ * 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>
+ */
+
+
+typedef struct DisasContext    DisasContext;
+typedef struct CPUAVRState     CPUAVRState;
+
+typedef union avr_opcode_NOP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 0000000000000000 */
+    };
+} avr_opcode_NOP_t;
+int     avr_translate_NOP(CPUAVRState *env, DisasContext *ctx, avr_opcode_NOP_t const *inst);
+
+typedef union avr_opcode_MOVW_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Rr:4;
+        uint16_t    Rd:4;
+        uint16_t:8; /* 00000001 */
+    };
+} avr_opcode_MOVW_t;
+int     avr_translate_MOVW(CPUAVRState *env, DisasContext *ctx, avr_opcode_MOVW_t const *inst);
+
+typedef union avr_opcode_MULS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Rr:4;
+        uint16_t    Rd:4;
+        uint16_t:8; /* 00000010 */
+    };
+} avr_opcode_MULS_t;
+int     avr_translate_MULS(CPUAVRState *env, DisasContext *ctx, avr_opcode_MULS_t const *inst);
+
+typedef union avr_opcode_MULSU_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Rr:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rd:3;
+        uint16_t:9; /* 000000110 */
+    };
+} avr_opcode_MULSU_t;
+int     avr_translate_MULSU(CPUAVRState *env, DisasContext *ctx, avr_opcode_MULSU_t const *inst);
+
+typedef union avr_opcode_FMUL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Rr:3;
+        uint16_t:1; /* 1 */
+        uint16_t    Rd:3;
+        uint16_t:9; /* 000000110 */
+    };
+} avr_opcode_FMUL_t;
+int     avr_translate_FMUL(CPUAVRState *env, DisasContext *ctx, avr_opcode_FMUL_t const *inst);
+
+typedef union avr_opcode_FMULS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Rr:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rd:3;
+        uint16_t:9; /* 000000111 */
+    };
+} avr_opcode_FMULS_t;
+int     avr_translate_FMULS(CPUAVRState *env, DisasContext *ctx, avr_opcode_FMULS_t const *inst);
+
+typedef union avr_opcode_FMULSU_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Rr:3;
+        uint16_t:1; /* 1 */
+        uint16_t    Rd:3;
+        uint16_t:9; /* 000000111 */
+    };
+} avr_opcode_FMULSU_t;
+int     avr_translate_FMULSU(CPUAVRState *env, DisasContext *ctx, avr_opcode_FMULSU_t const *inst);
+
+typedef union avr_opcode_CPC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 000001 */
+    };
+} avr_opcode_CPC_t;
+int     avr_translate_CPC(CPUAVRState *env, DisasContext *ctx, avr_opcode_CPC_t const *inst);
+
+typedef union avr_opcode_SBC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 000010 */
+    };
+} avr_opcode_SBC_t;
+int     avr_translate_SBC(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBC_t const *inst);
+
+typedef union avr_opcode_ADD_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 000011 */
+    };
+} avr_opcode_ADD_t;
+int     avr_translate_ADD(CPUAVRState *env, DisasContext *ctx, avr_opcode_ADD_t const *inst);
+
+typedef union avr_opcode_AND_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 001000 */
+    };
+} avr_opcode_AND_t;
+int     avr_translate_AND(CPUAVRState *env, DisasContext *ctx, avr_opcode_AND_t const *inst);
+
+typedef union avr_opcode_EOR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 001001 */
+    };
+} avr_opcode_EOR_t;
+int     avr_translate_EOR(CPUAVRState *env, DisasContext *ctx, avr_opcode_EOR_t const *inst);
+
+typedef union avr_opcode_OR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 001010 */
+    };
+} avr_opcode_OR_t;
+int     avr_translate_OR(CPUAVRState *env, DisasContext *ctx, avr_opcode_OR_t const *inst);
+
+typedef union avr_opcode_MOV_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 001011 */
+    };
+} avr_opcode_MOV_t;
+int     avr_translate_MOV(CPUAVRState *env, DisasContext *ctx, avr_opcode_MOV_t const *inst);
+
+typedef union avr_opcode_CPSE_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 000100 */
+    };
+} avr_opcode_CPSE_t;
+int     avr_translate_CPSE(CPUAVRState *env, DisasContext *ctx, avr_opcode_CPSE_t const *inst);
+
+typedef union avr_opcode_CP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 000101 */
+    };
+} avr_opcode_CP_t;
+int     avr_translate_CP(CPUAVRState *env, DisasContext *ctx, avr_opcode_CP_t const *inst);
+
+typedef union avr_opcode_SUB_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 000110 */
+    };
+} avr_opcode_SUB_t;
+int     avr_translate_SUB(CPUAVRState *env, DisasContext *ctx, avr_opcode_SUB_t const *inst);
+
+typedef union avr_opcode_ADC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 000111 */
+    };
+} avr_opcode_ADC_t;
+int     avr_translate_ADC(CPUAVRState *env, DisasContext *ctx, avr_opcode_ADC_t const *inst);
+
+typedef union avr_opcode_CPI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:4;
+        uint16_t    hImm:4;
+        uint16_t:4; /* 0011 */
+    };
+} avr_opcode_CPI_t;
+int     avr_translate_CPI(CPUAVRState *env, DisasContext *ctx, avr_opcode_CPI_t const *inst);
+
+typedef union avr_opcode_SBCI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:4;
+        uint16_t    hImm:4;
+        uint16_t:4; /* 0100 */
+    };
+} avr_opcode_SBCI_t;
+int     avr_translate_SBCI(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBCI_t const *inst);
+
+typedef union avr_opcode_ORI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:4;
+        uint16_t    hImm:4;
+        uint16_t:4; /* 0110 */
+    };
+} avr_opcode_ORI_t;
+int     avr_translate_ORI(CPUAVRState *env, DisasContext *ctx, avr_opcode_ORI_t const *inst);
+
+typedef union avr_opcode_SUBI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:4;
+        uint16_t    hImm:4;
+        uint16_t:4; /* 0101 */
+    };
+} avr_opcode_SUBI_t;
+int     avr_translate_SUBI(CPUAVRState *env, DisasContext *ctx, avr_opcode_SUBI_t const *inst);
+
+typedef union avr_opcode_ANDI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:4;
+        uint16_t    hImm:4;
+        uint16_t:4; /* 0111 */
+    };
+} avr_opcode_ANDI_t;
+int     avr_translate_ANDI(CPUAVRState *env, DisasContext *ctx, avr_opcode_ANDI_t const *inst);
+
+typedef union avr_opcode_LDDZ_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 0 */
+        uint16_t    mImm:2;
+        uint16_t:1; /* 0 */
+        uint16_t    hImm:1;
+        uint16_t:2; /* 10 */
+    };
+} avr_opcode_LDDZ_t;
+int     avr_translate_LDDZ(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDDZ_t const *inst);
+
+typedef union avr_opcode_LDDY_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:3;
+        uint16_t:1; /* 1 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 0 */
+        uint16_t    mImm:2;
+        uint16_t:1; /* 0 */
+        uint16_t    hImm:1;
+        uint16_t:2; /* 10 */
+    };
+} avr_opcode_LDDY_t;
+int     avr_translate_LDDY(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDDY_t const *inst);
+
+typedef union avr_opcode_STDZ_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 1 */
+        uint16_t    mImm:2;
+        uint16_t:1; /* 0 */
+        uint16_t    hImm:1;
+        uint16_t:2; /* 10 */
+    };
+} avr_opcode_STDZ_t;
+int     avr_translate_STDZ(CPUAVRState *env, DisasContext *ctx, avr_opcode_STDZ_t const *inst);
+
+typedef union avr_opcode_STDY_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:3;
+        uint16_t:1; /* 1 */
+        uint16_t    Rd:5;
+        uint16_t:1; /* 1 */
+        uint16_t    mImm:2;
+        uint16_t:1; /* 0 */
+        uint16_t    hImm:1;
+        uint16_t:2; /* 10 */
+    };
+} avr_opcode_STDY_t;
+int     avr_translate_STDY(CPUAVRState *env, DisasContext *ctx, avr_opcode_STDY_t const *inst);
+
+typedef union avr_opcode_LDS_u {
+    uint32_t    opcode;
+    struct {
+        uint32_t    Imm:16;
+        uint32_t:4; /* 0000 */
+        uint32_t    Rd:5;
+        uint32_t:7; /* 1001000 */
+    };
+} avr_opcode_LDS_t;
+int     avr_translate_LDS(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDS_t const *inst);
+
+typedef union avr_opcode_LDZ2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0001 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LDZ2_t;
+int     avr_translate_LDZ2(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDZ2_t const *inst);
+
+typedef union avr_opcode_LDZ3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0010 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LDZ3_t;
+int     avr_translate_LDZ3(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDZ3_t const *inst);
+
+typedef union avr_opcode_LPM2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0100 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LPM2_t;
+int     avr_translate_LPM2(CPUAVRState *env, DisasContext *ctx, avr_opcode_LPM2_t const *inst);
+
+typedef union avr_opcode_LPMX_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0101 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LPMX_t;
+int     avr_translate_LPMX(CPUAVRState *env, DisasContext *ctx, avr_opcode_LPMX_t const *inst);
+
+typedef union avr_opcode_ELPM2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0110 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_ELPM2_t;
+int     avr_translate_ELPM2(CPUAVRState *env, DisasContext *ctx, avr_opcode_ELPM2_t const *inst);
+
+typedef union avr_opcode_ELPMX_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0111 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_ELPMX_t;
+int     avr_translate_ELPMX(CPUAVRState *env, DisasContext *ctx, avr_opcode_ELPMX_t const *inst);
+
+typedef union avr_opcode_LDY2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1001 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LDY2_t;
+int     avr_translate_LDY2(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDY2_t const *inst);
+
+typedef union avr_opcode_LDY3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1010 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LDY3_t;
+int     avr_translate_LDY3(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDY3_t const *inst);
+
+typedef union avr_opcode_LDX1_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1100 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LDX1_t;
+int     avr_translate_LDX1(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDX1_t const *inst);
+
+typedef union avr_opcode_LDX2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1101 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LDX2_t;
+int     avr_translate_LDX2(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDX2_t const *inst);
+
+typedef union avr_opcode_LDX3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1110 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_LDX3_t;
+int     avr_translate_LDX3(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDX3_t const *inst);
+
+typedef union avr_opcode_POP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1111 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001000 */
+    };
+} avr_opcode_POP_t;
+int     avr_translate_POP(CPUAVRState *env, DisasContext *ctx, avr_opcode_POP_t const *inst);
+
+typedef union avr_opcode_STS_u {
+    uint32_t    opcode;
+    struct {
+        uint32_t    Imm:16;
+        uint32_t:4; /* 0000 */
+        uint32_t    Rd:5;
+        uint32_t:7; /* 1001001 */
+    };
+} avr_opcode_STS_t;
+int     avr_translate_STS(CPUAVRState *env, DisasContext *ctx, avr_opcode_STS_t const *inst);
+
+typedef union avr_opcode_STZ2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0001 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_STZ2_t;
+int     avr_translate_STZ2(CPUAVRState *env, DisasContext *ctx, avr_opcode_STZ2_t const *inst);
+
+typedef union avr_opcode_STZ3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0010 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_STZ3_t;
+int     avr_translate_STZ3(CPUAVRState *env, DisasContext *ctx, avr_opcode_STZ3_t const *inst);
+
+typedef union avr_opcode_XCH_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0100 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_XCH_t;
+int     avr_translate_XCH(CPUAVRState *env, DisasContext *ctx, avr_opcode_XCH_t const *inst);
+
+typedef union avr_opcode_LAS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0101 */
+        uint16_t    Rr:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_LAS_t;
+int     avr_translate_LAS(CPUAVRState *env, DisasContext *ctx, avr_opcode_LAS_t const *inst);
+
+typedef union avr_opcode_LAC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0110 */
+        uint16_t    Rr:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_LAC_t;
+int     avr_translate_LAC(CPUAVRState *env, DisasContext *ctx, avr_opcode_LAC_t const *inst);
+
+typedef union avr_opcode_LAT_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0111 */
+        uint16_t    Rr:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_LAT_t;
+int     avr_translate_LAT(CPUAVRState *env, DisasContext *ctx, avr_opcode_LAT_t const *inst);
+
+typedef union avr_opcode_STY2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1001 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_STY2_t;
+int     avr_translate_STY2(CPUAVRState *env, DisasContext *ctx, avr_opcode_STY2_t const *inst);
+
+typedef union avr_opcode_STY3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1010 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_STY3_t;
+int     avr_translate_STY3(CPUAVRState *env, DisasContext *ctx, avr_opcode_STY3_t const *inst);
+
+typedef union avr_opcode_STX1_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1100 */
+        uint16_t    Rr:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_STX1_t;
+int     avr_translate_STX1(CPUAVRState *env, DisasContext *ctx, avr_opcode_STX1_t const *inst);
+
+typedef union avr_opcode_STX2_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1101 */
+        uint16_t    Rr:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_STX2_t;
+int     avr_translate_STX2(CPUAVRState *env, DisasContext *ctx, avr_opcode_STX2_t const *inst);
+
+typedef union avr_opcode_STX3_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1110 */
+        uint16_t    Rr:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_STX3_t;
+int     avr_translate_STX3(CPUAVRState *env, DisasContext *ctx, avr_opcode_STX3_t const *inst);
+
+typedef union avr_opcode_PUSH_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1111 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001001 */
+    };
+} avr_opcode_PUSH_t;
+int     avr_translate_PUSH(CPUAVRState *env, DisasContext *ctx, avr_opcode_PUSH_t const *inst);
+
+typedef union avr_opcode_COM_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0000 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001010 */
+    };
+} avr_opcode_COM_t;
+int     avr_translate_COM(CPUAVRState *env, DisasContext *ctx, avr_opcode_COM_t const *inst);
+
+typedef union avr_opcode_NEG_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0001 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001010 */
+    };
+} avr_opcode_NEG_t;
+int     avr_translate_NEG(CPUAVRState *env, DisasContext *ctx, avr_opcode_NEG_t const *inst);
+
+typedef union avr_opcode_SWAP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0010 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001010 */
+    };
+} avr_opcode_SWAP_t;
+int     avr_translate_SWAP(CPUAVRState *env, DisasContext *ctx, avr_opcode_SWAP_t const *inst);
+
+typedef union avr_opcode_INC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0011 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001010 */
+    };
+} avr_opcode_INC_t;
+int     avr_translate_INC(CPUAVRState *env, DisasContext *ctx, avr_opcode_INC_t const *inst);
+
+typedef union avr_opcode_ASR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0101 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001010 */
+    };
+} avr_opcode_ASR_t;
+int     avr_translate_ASR(CPUAVRState *env, DisasContext *ctx, avr_opcode_ASR_t const *inst);
+
+typedef union avr_opcode_LSR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0110 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001010 */
+    };
+} avr_opcode_LSR_t;
+int     avr_translate_LSR(CPUAVRState *env, DisasContext *ctx, avr_opcode_LSR_t const *inst);
+
+typedef union avr_opcode_ROR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 0111 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001010 */
+    };
+} avr_opcode_ROR_t;
+int     avr_translate_ROR(CPUAVRState *env, DisasContext *ctx, avr_opcode_ROR_t const *inst);
+
+typedef union avr_opcode_BSET_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1000 */
+        uint16_t    Bit:3;
+        uint16_t:9; /* 100101000 */
+    };
+} avr_opcode_BSET_t;
+int     avr_translate_BSET(CPUAVRState *env, DisasContext *ctx, avr_opcode_BSET_t const *inst);
+
+typedef union avr_opcode_IJMP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010000001001 */
+    };
+} avr_opcode_IJMP_t;
+int     avr_translate_IJMP(CPUAVRState *env, DisasContext *ctx, avr_opcode_IJMP_t const *inst);
+
+typedef union avr_opcode_EIJMP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010000011001 */
+    };
+} avr_opcode_EIJMP_t;
+int     avr_translate_EIJMP(CPUAVRState *env, DisasContext *ctx, avr_opcode_EIJMP_t const *inst);
+
+typedef union avr_opcode_BCLR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1000 */
+        uint16_t    Bit:3;
+        uint16_t:9; /* 100101001 */
+    };
+} avr_opcode_BCLR_t;
+int     avr_translate_BCLR(CPUAVRState *env, DisasContext *ctx, avr_opcode_BCLR_t const *inst);
+
+typedef union avr_opcode_RET_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010100001000 */
+    };
+} avr_opcode_RET_t;
+int     avr_translate_RET(CPUAVRState *env, DisasContext *ctx, avr_opcode_RET_t const *inst);
+
+typedef union avr_opcode_RETI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010100011000 */
+    };
+} avr_opcode_RETI_t;
+int     avr_translate_RETI(CPUAVRState *env, DisasContext *ctx, avr_opcode_RETI_t const *inst);
+
+typedef union avr_opcode_ICALL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010100001001 */
+    };
+} avr_opcode_ICALL_t;
+int     avr_translate_ICALL(CPUAVRState *env, DisasContext *ctx, avr_opcode_ICALL_t const *inst);
+
+typedef union avr_opcode_EICALL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010100011001 */
+    };
+} avr_opcode_EICALL_t;
+int     avr_translate_EICALL(CPUAVRState *env, DisasContext *ctx, avr_opcode_EICALL_t const *inst);
+
+typedef union avr_opcode_SLEEP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010110001000 */
+    };
+} avr_opcode_SLEEP_t;
+int     avr_translate_SLEEP(CPUAVRState *env, DisasContext *ctx, avr_opcode_SLEEP_t const *inst);
+
+typedef union avr_opcode_BREAK_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010110011000 */
+    };
+} avr_opcode_BREAK_t;
+int     avr_translate_BREAK(CPUAVRState *env, DisasContext *ctx, avr_opcode_BREAK_t const *inst);
+
+typedef union avr_opcode_WDR_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010110101000 */
+    };
+} avr_opcode_WDR_t;
+int     avr_translate_WDR(CPUAVRState *env, DisasContext *ctx, avr_opcode_WDR_t const *inst);
+
+typedef union avr_opcode_LPM1_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010111001000 */
+    };
+} avr_opcode_LPM1_t;
+int     avr_translate_LPM1(CPUAVRState *env, DisasContext *ctx, avr_opcode_LPM1_t const *inst);
+
+typedef union avr_opcode_ELPM1_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010111011000 */
+    };
+} avr_opcode_ELPM1_t;
+int     avr_translate_ELPM1(CPUAVRState *env, DisasContext *ctx, avr_opcode_ELPM1_t const *inst);
+
+typedef union avr_opcode_SPM_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010111101000 */
+    };
+} avr_opcode_SPM_t;
+int     avr_translate_SPM(CPUAVRState *env, DisasContext *ctx, avr_opcode_SPM_t const *inst);
+
+typedef union avr_opcode_SPMX_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:16; /* 1001010111111000 */
+    };
+} avr_opcode_SPMX_t;
+int     avr_translate_SPMX(CPUAVRState *env, DisasContext *ctx, avr_opcode_SPMX_t const *inst);
+
+typedef union avr_opcode_DEC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1010 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1001010 */
+    };
+} avr_opcode_DEC_t;
+int     avr_translate_DEC(CPUAVRState *env, DisasContext *ctx, avr_opcode_DEC_t const *inst);
+
+typedef union avr_opcode_DES_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t:4; /* 1011 */
+        uint16_t    Imm:4;
+        uint16_t:8; /* 10010100 */
+    };
+} avr_opcode_DES_t;
+int     avr_translate_DES(CPUAVRState *env, DisasContext *ctx, avr_opcode_DES_t const *inst);
+
+typedef union avr_opcode_JMP_u {
+    uint32_t    opcode;
+    struct {
+        uint32_t    lImm:17;
+        uint32_t:3; /* 110 */
+        uint32_t    hImm:5;
+        uint32_t:7; /* 1001010 */
+    };
+} avr_opcode_JMP_t;
+int     avr_translate_JMP(CPUAVRState *env, DisasContext *ctx, avr_opcode_JMP_t const *inst);
+
+typedef union avr_opcode_CALL_u {
+    uint32_t    opcode;
+    struct {
+        uint32_t    lImm:17;
+        uint32_t:3; /* 111 */
+        uint32_t    hImm:5;
+        uint32_t:7; /* 1001010 */
+    };
+} avr_opcode_CALL_t;
+int     avr_translate_CALL(CPUAVRState *env, DisasContext *ctx, avr_opcode_CALL_t const *inst);
+
+typedef union avr_opcode_ADIW_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:2;
+        uint16_t    hImm:2;
+        uint16_t:8; /* 10010110 */
+    };
+} avr_opcode_ADIW_t;
+int     avr_translate_ADIW(CPUAVRState *env, DisasContext *ctx, avr_opcode_ADIW_t const *inst);
+
+typedef union avr_opcode_SBIW_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:2;
+        uint16_t    hImm:2;
+        uint16_t:8; /* 10010111 */
+    };
+} avr_opcode_SBIW_t;
+int     avr_translate_SBIW(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBIW_t const *inst);
+
+typedef union avr_opcode_CBI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t    Imm:5;
+        uint16_t:8; /* 10011000 */
+    };
+} avr_opcode_CBI_t;
+int     avr_translate_CBI(CPUAVRState *env, DisasContext *ctx, avr_opcode_CBI_t const *inst);
+
+typedef union avr_opcode_SBIC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t    Imm:5;
+        uint16_t:8; /* 10011001 */
+    };
+} avr_opcode_SBIC_t;
+int     avr_translate_SBIC(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBIC_t const *inst);
+
+typedef union avr_opcode_SBI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t    Imm:5;
+        uint16_t:8; /* 10011010 */
+    };
+} avr_opcode_SBI_t;
+int     avr_translate_SBI(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBI_t const *inst);
+
+typedef union avr_opcode_SBIS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t    Imm:5;
+        uint16_t:8; /* 10011011 */
+    };
+} avr_opcode_SBIS_t;
+int     avr_translate_SBIS(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBIS_t const *inst);
+
+typedef union avr_opcode_MUL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lRr:4;
+        uint16_t    Rd:5;
+        uint16_t    hRr:1;
+        uint16_t:6; /* 100111 */
+    };
+} avr_opcode_MUL_t;
+int     avr_translate_MUL(CPUAVRState *env, DisasContext *ctx, avr_opcode_MUL_t const *inst);
+
+typedef union avr_opcode_IN_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:5;
+        uint16_t    hImm:2;
+        uint16_t:5; /* 10110 */
+    };
+} avr_opcode_IN_t;
+int     avr_translate_IN(CPUAVRState *env, DisasContext *ctx, avr_opcode_IN_t const *inst);
+
+typedef union avr_opcode_OUT_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:5;
+        uint16_t    hImm:2;
+        uint16_t:5; /* 10111 */
+    };
+} avr_opcode_OUT_t;
+int     avr_translate_OUT(CPUAVRState *env, DisasContext *ctx, avr_opcode_OUT_t const *inst);
+
+typedef union avr_opcode_RJMP_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Imm:12;
+        uint16_t:4; /* 1100 */
+    };
+} avr_opcode_RJMP_t;
+int     avr_translate_RJMP(CPUAVRState *env, DisasContext *ctx, avr_opcode_RJMP_t const *inst);
+
+typedef union avr_opcode_LDI_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    lImm:4;
+        uint16_t    Rd:4;
+        uint16_t    hImm:4;
+        uint16_t:4; /* 1110 */
+    };
+} avr_opcode_LDI_t;
+int     avr_translate_LDI(CPUAVRState *env, DisasContext *ctx, avr_opcode_LDI_t const *inst);
+
+typedef union avr_opcode_RCALL_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Imm:12;
+        uint16_t:4; /* 1101 */
+    };
+} avr_opcode_RCALL_t;
+int     avr_translate_RCALL(CPUAVRState *env, DisasContext *ctx, avr_opcode_RCALL_t const *inst);
+
+typedef union avr_opcode_BRBS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t    Imm:7;
+        uint16_t:6; /* 111100 */
+    };
+} avr_opcode_BRBS_t;
+int     avr_translate_BRBS(CPUAVRState *env, DisasContext *ctx, avr_opcode_BRBS_t const *inst);
+
+typedef union avr_opcode_BRBC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t    Imm:7;
+        uint16_t:6; /* 111101 */
+    };
+} avr_opcode_BRBC_t;
+int     avr_translate_BRBC(CPUAVRState *env, DisasContext *ctx, avr_opcode_BRBC_t const *inst);
+
+typedef union avr_opcode_BLD_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1111100 */
+    };
+} avr_opcode_BLD_t;
+int     avr_translate_BLD(CPUAVRState *env, DisasContext *ctx, avr_opcode_BLD_t const *inst);
+
+typedef union avr_opcode_BST_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rd:5;
+        uint16_t:7; /* 1111101 */
+    };
+} avr_opcode_BST_t;
+int     avr_translate_BST(CPUAVRState *env, DisasContext *ctx, avr_opcode_BST_t const *inst);
+
+typedef union avr_opcode_SBRC_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rr:5;
+        uint16_t:7; /* 1111110 */
+    };
+} avr_opcode_SBRC_t;
+int     avr_translate_SBRC(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBRC_t const *inst);
+
+typedef union avr_opcode_SBRS_u {
+    uint16_t    opcode;
+    struct {
+        uint16_t    Bit:3;
+        uint16_t:1; /* 0 */
+        uint16_t    Rr:5;
+        uint16_t:7; /* 1111111 */
+    };
+} avr_opcode_SBRS_t;
+int     avr_translate_SBRS(CPUAVRState *env, DisasContext *ctx, avr_opcode_SBRS_t const *inst);
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH 5/9] adding AVR interrupt handling
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
                   ` (2 preceding siblings ...)
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 4/9] adding instructions encodings for LE and BE compilers Michael Rolnik
@ 2016-05-30  1:23 ` Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 6/9] adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions Michael Rolnik
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-avr/helper.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 63 insertions(+), 1 deletion(-)

diff --git a/target-avr/helper.c b/target-avr/helper.c
index aec37af..ed22b37 100644
--- a/target-avr/helper.c
+++ b/target-avr/helper.c
@@ -33,12 +33,74 @@ bool                avr_cpu_exec_interrupt(
                                 CPUState               *cs,
                                 int                     interrupt_request)
 {
-    return  false;
+    CPUClass    *cc  = CPU_GET_CLASS(cs);
+    AVRCPU      *cpu = AVR_CPU(cs);
+    CPUAVRState *env = &cpu->env;
+
+    bool    ret = false;
+
+    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   = __builtin_ffs(env->intsrc) - 1;
+            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;
+    int         vector;
+    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  = __builtin_ffs(env->intsrc);
+    }
+
+    if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+        stb_phys(cs->as, env->sp--, (ret & 0x0000ff));
+        stb_phys(cs->as, env->sp--, (ret & 0x00ff00) >>  8);
+        stb_phys(cs->as, env->sp--, (ret & 0xff0000) >> 16);
+
+        env->pc = base + vector * size;
+    } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) {
+        stb_phys(cs->as, env->sp--, (ret & 0x0000ff));
+        stb_phys(cs->as, env->sp--, (ret & 0x00ff00) >>  8);
+
+        env->pc = base + vector * size;
+    } else {
+        stb_phys(cs->as, env->sp--, (ret & 0x0000ff));
+
+        env->pc = base + vector * size;
+    }
+
+    env->sregI  = 0;    /*  clear Global Interrupt Flag */
+
+    cs->exception_index = -1;
 }
 
 int                 avr_cpu_memory_rw_debug(
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH 6/9] adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
                   ` (3 preceding siblings ...)
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 5/9] adding AVR interrupt handling Michael Rolnik
@ 2016-05-30  1:23 ` Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 7/9] adding instruction decoder Michael Rolnik
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-avr/helper.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 target-avr/helper.h |   5 +++
 2 files changed, 108 insertions(+)

diff --git a/target-avr/helper.c b/target-avr/helper.c
index ed22b37..450f598 100644
--- a/target-avr/helper.c
+++ b/target-avr/helper.c
@@ -155,6 +155,23 @@ void                tlb_fill(
 
     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));
+
+    cs->exception_index = EXCP_DEBUG;
+    cpu_dump_state(cs, stderr, fprintf, 0);
+    cpu_loop_exit(cs);
+}
 
 void                helper_debug(
                                 CPUAVRState        *env)
@@ -165,3 +182,89 @@ void                helper_debug(
     cpu_loop_exit(cs);
 }
 
+void                helper_wdr(
+                                CPUAVRState        *env)
+{
+    CPUState   *cs = CPU(avr_env_get_cpu(env));
+
+    cs->exception_index = EXCP_DEBUG;
+    cpu_loop_exit(cs);
+}
+
+target_ulong        helper_inb(
+                                CPUAVRState        *env,
+                                uint32_t            port)
+{
+    printf("in: io[%02x]\n", port);
+
+    switch (port) {
+        case    0x3b: {
+            return  env->rampZ;         /*  RAMPZ */
+        }
+        case    0x3d: {                 /*  SPL */
+            return  env->sp & 0x00ff;
+        }
+        case    0x3e: {                 /*  SPH */
+            return  env->sp >> 8;
+        }
+        case    0x3f: {                 /*  SREG */
+            uint8_t sreg;
+            sreg    =   (env->sregC & 0x01) << 0
+                    |   (env->sregZ & 0x01) << 1
+                    |   (env->sregN & 0x01) << 2
+                    |   (env->sregV & 0x01) << 3
+                    |   (env->sregS & 0x01) << 4
+                    |   (env->sregH & 0x01) << 5
+                    |   (env->sregT & 0x01) << 6
+                    |   (env->sregI & 0x01) << 7;
+            return  sreg;
+        }
+    }
+    return  0;
+}
+
+void                helper_outb(
+                                CPUAVRState        *env,
+                                uint32_t            port,
+                                uint32_t            data)
+{
+    printf("out:%02x -> io[%02x]\n", data, port);
+
+    data    &= 0x000000ff;
+
+    switch (port) {
+        case    0x04: {
+            qemu_irq    irq;
+            CPUState   *cpu = CPU(avr_env_get_cpu(env));
+            irq     = qdev_get_gpio_in(DEVICE(cpu), 3);
+            qemu_set_irq(irq, 1);
+            break;
+        }
+        case    0x3b: {
+            env->rampZ  = data & 0x01;  /*  RAMPZ */
+            break;
+        }
+        case    0x3d: {                 /*  SPL */
+            if (avr_feature(env, AVR_FEATURE_2_BYTE_SP)) {
+                env->sp = (env->sp & 0xff00) | (data);
+            }
+            break;
+        }
+        case    0x3e: {                  /*  SPH */
+            env->sp = (env->sp & 0x00ff) | (data << 8);
+            break;
+        }
+        case    0x3f: {                 /*  SREG */
+            env->sregC  = (data >> 0) & 0x01;
+            env->sregZ  = (data >> 1) & 0x01;
+            env->sregN  = (data >> 2) & 0x01;
+            env->sregV  = (data >> 3) & 0x01;
+            env->sregS  = (data >> 4) & 0x01;
+            env->sregH  = (data >> 5) & 0x01;
+            env->sregT  = (data >> 6) & 0x01;
+            env->sregI  = (data >> 7) & 0x01;
+            break;
+        }
+    }
+}
+
diff --git a/target-avr/helper.h b/target-avr/helper.h
index 017e076..5a08cfd 100644
--- a/target-avr/helper.h
+++ b/target-avr/helper.h
@@ -18,4 +18,9 @@
  * <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)
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH 7/9] adding instruction decoder
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
                   ` (4 preceding siblings ...)
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 6/9] adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions Michael Rolnik
@ 2016-05-30  1:23 ` Michael Rolnik
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 8/9] adding instruction translations Michael Rolnik
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-avr/decode.c | 732 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 732 insertions(+)
 create mode 100644 target-avr/decode.c

diff --git a/target-avr/decode.c b/target-avr/decode.c
new file mode 100644
index 0000000..f517045
--- /dev/null
+++ b/target-avr/decode.c
@@ -0,0 +1,732 @@
+/*
+ * 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>
+#ifdef HOST_WORDS_BIGENDIAN
+#include "inst-be.h"
+#else
+#include "inst-le.h"
+#endif
+
+
+typedef int (*translate_function_t)(CPUAVRState *env, DisasContext* ctx, uint8_t const *opcode);
+uint32_t    avr_decode(uint32_t pc, uint32_t *length, uint8_t *code, translate_function_t *translate);
+uint32_t    get_opcode(uint8_t const *code, unsigned bitBase, unsigned bitSsize);
+
+uint32_t    avr_decode(uint32_t pc, uint32_t *length, uint8_t *code, translate_function_t *translate)
+{
+    uint32_t    opcode  = get_opcode(code, 0, 16);
+    switch (opcode & 0x0000d000) {
+        case    0x00000000: {
+            uint32_t    opcode  = get_opcode(code, 0, 16);
+            switch (opcode & 0x00002c00) {
+                case    0x00000000: {
+                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                    switch (opcode & 0x00000300) {
+                        case    0x00000000: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_NOP;
+                            break;
+                        }
+                        case    0x00000100: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_MOVW;
+                            break;
+                        }
+                        case    0x00000200: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_MULS;
+                            break;
+                        }
+                        case    0x00000300: {
+                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                            switch (opcode & 0x00000088) {
+                                case    0x00000000: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_MULSU;
+                                    break;
+                                }
+                                case    0x00000008: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_FMUL;
+                                    break;
+                                }
+                                case    0x00000080: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_FMULS;
+                                    break;
+                                }
+                                case    0x00000088: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_FMULSU;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case    0x00000400: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_CPC;
+                    break;
+                }
+                case    0x00000800: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_SBC;
+                    break;
+                }
+                case    0x00000c00: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_ADD;
+                    break;
+                }
+                case    0x00002000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_AND;
+                    break;
+                }
+                case    0x00002400: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_EOR;
+                    break;
+                }
+                case    0x00002800: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_OR;
+                    break;
+                }
+                case    0x00002c00: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_MOV;
+                    break;
+                }
+            }
+            break;
+        }
+        case    0x00001000: {
+            uint32_t    opcode  = get_opcode(code, 0, 16);
+            switch (opcode & 0x00002000) {
+                case    0x00000000: {
+                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                    switch (opcode & 0x00000c00) {
+                        case    0x00000000: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_CPSE;
+                            break;
+                        }
+                        case    0x00000400: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_CP;
+                            break;
+                        }
+                        case    0x00000800: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_SUB;
+                            break;
+                        }
+                        case    0x00000c00: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_ADC;
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case    0x00002000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_CPI;
+                    break;
+                }
+            }
+            break;
+        }
+        case    0x00004000: {
+            uint32_t    opcode  = get_opcode(code, 0, 16);
+            switch (opcode & 0x00002000) {
+                case    0x00000000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_SBCI;
+                    break;
+                }
+                case    0x00002000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_ORI;
+                    break;
+                }
+            }
+            break;
+        }
+        case    0x00005000: {
+            uint32_t    opcode  = get_opcode(code, 0, 16);
+            switch (opcode & 0x00002000) {
+                case    0x00000000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_SUBI;
+                    break;
+                }
+                case    0x00002000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_ANDI;
+                    break;
+                }
+            }
+            break;
+        }
+        case    0x00008000: {
+            uint32_t    opcode  = get_opcode(code, 0, 16);
+            switch (opcode & 0x00000208) {
+                case    0x00000000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_LDDZ;
+                    break;
+                }
+                case    0x00000008: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_LDDY;
+                    break;
+                }
+                case    0x00000200: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_STDZ;
+                    break;
+                }
+                case    0x00000208: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_STDY;
+                    break;
+                }
+            }
+            break;
+        }
+        case    0x00009000: {
+            uint32_t    opcode  = get_opcode(code, 0, 16);
+            switch (opcode & 0x00002800) {
+                case    0x00000000: {
+                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                    switch (opcode & 0x00000600) {
+                        case    0x00000000: {
+                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                            switch (opcode & 0x0000000f) {
+                                case    0x00000000: {
+                                    *length = 32;
+                                    *translate = (translate_function_t)&avr_translate_LDS;
+                                    break;
+                                }
+                                case    0x00000001: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LDZ2;
+                                    break;
+                                }
+                                case    0x00000002: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LDZ3;
+                                    break;
+                                }
+                                case    0x00000003: {
+                                    break;
+                                }
+                                case    0x00000004: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LPM2;
+                                    break;
+                                }
+                                case    0x00000005: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LPMX;
+                                    break;
+                                }
+                                case    0x00000006: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_ELPM2;
+                                    break;
+                                }
+                                case    0x00000007: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_ELPMX;
+                                    break;
+                                }
+                                case    0x00000008: {
+                                    break;
+                                }
+                                case    0x00000009: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LDY2;
+                                    break;
+                                }
+                                case    0x0000000a: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LDY3;
+                                    break;
+                                }
+                                case    0x0000000b: {
+                                    break;
+                                }
+                                case    0x0000000c: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LDX1;
+                                    break;
+                                }
+                                case    0x0000000d: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LDX2;
+                                    break;
+                                }
+                                case    0x0000000e: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LDX3;
+                                    break;
+                                }
+                                case    0x0000000f: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_POP;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case    0x00000200: {
+                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                            switch (opcode & 0x0000000f) {
+                                case    0x00000000: {
+                                    *length = 32;
+                                    *translate = (translate_function_t)&avr_translate_STS;
+                                    break;
+                                }
+                                case    0x00000001: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_STZ2;
+                                    break;
+                                }
+                                case    0x00000002: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_STZ3;
+                                    break;
+                                }
+                                case    0x00000003: {
+                                    break;
+                                }
+                                case    0x00000004: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_XCH;
+                                    break;
+                                }
+                                case    0x00000005: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LAS;
+                                    break;
+                                }
+                                case    0x00000006: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LAC;
+                                    break;
+                                }
+                                case    0x00000007: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_LAT;
+                                    break;
+                                }
+                                case    0x00000008: {
+                                    break;
+                                }
+                                case    0x00000009: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_STY2;
+                                    break;
+                                }
+                                case    0x0000000a: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_STY3;
+                                    break;
+                                }
+                                case    0x0000000b: {
+                                    break;
+                                }
+                                case    0x0000000c: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_STX1;
+                                    break;
+                                }
+                                case    0x0000000d: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_STX2;
+                                    break;
+                                }
+                                case    0x0000000e: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_STX3;
+                                    break;
+                                }
+                                case    0x0000000f: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_PUSH;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case    0x00000400: {
+                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                            switch (opcode & 0x0000000e) {
+                                case    0x00000000: {
+                                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                                    switch (opcode & 0x00000001) {
+                                        case    0x00000000: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_COM;
+                                            break;
+                                        }
+                                        case    0x00000001: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_NEG;
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case    0x00000002: {
+                                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                                    switch (opcode & 0x00000001) {
+                                        case    0x00000000: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_SWAP;
+                                            break;
+                                        }
+                                        case    0x00000001: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_INC;
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case    0x00000004: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_ASR;
+                                    break;
+                                }
+                                case    0x00000006: {
+                                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                                    switch (opcode & 0x00000001) {
+                                        case    0x00000000: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_LSR;
+                                            break;
+                                        }
+                                        case    0x00000001: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_ROR;
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case    0x00000008: {
+                                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                                    switch (opcode & 0x00000181) {
+                                        case    0x00000000: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_BSET;
+                                            break;
+                                        }
+                                        case    0x00000001: {
+                                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                                            switch (opcode & 0x00000010) {
+                                                case    0x00000000: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_IJMP;
+                                                    break;
+                                                }
+                                                case    0x00000010: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_EIJMP;
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        case    0x00000080: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_BCLR;
+                                            break;
+                                        }
+                                        case    0x00000081: {
+                                            break;
+                                        }
+                                        case    0x00000100: {
+                                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                                            switch (opcode & 0x00000010) {
+                                                case    0x00000000: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_RET;
+                                                    break;
+                                                }
+                                                case    0x00000010: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_RETI;
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        case    0x00000101: {
+                                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                                            switch (opcode & 0x00000010) {
+                                                case    0x00000000: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_ICALL;
+                                                    break;
+                                                }
+                                                case    0x00000010: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_EICALL;
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        case    0x00000180: {
+                                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                                            switch (opcode & 0x00000070) {
+                                                case    0x00000000: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_SLEEP;
+                                                    break;
+                                                }
+                                                case    0x00000010: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_BREAK;
+                                                    break;
+                                                }
+                                                case    0x00000020: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_WDR;
+                                                    break;
+                                                }
+                                                case    0x00000030: {
+                                                    break;
+                                                }
+                                                case    0x00000040: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_LPM1;
+                                                    break;
+                                                }
+                                                case    0x00000050: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_ELPM1;
+                                                    break;
+                                                }
+                                                case    0x00000060: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_SPM;
+                                                    break;
+                                                }
+                                                case    0x00000070: {
+                                                    *length = 16;
+                                                    *translate = (translate_function_t)&avr_translate_SPMX;
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        case    0x00000181: {
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case    0x0000000a: {
+                                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                                    switch (opcode & 0x00000001) {
+                                        case    0x00000000: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_DEC;
+                                            break;
+                                        }
+                                        case    0x00000001: {
+                                            *length = 16;
+                                            *translate = (translate_function_t)&avr_translate_DES;
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case    0x0000000c: {
+                                    *length = 32;
+                                    *translate = (translate_function_t)&avr_translate_JMP;
+                                    break;
+                                }
+                                case    0x0000000e: {
+                                    *length = 32;
+                                    *translate = (translate_function_t)&avr_translate_CALL;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case    0x00000600: {
+                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                            switch (opcode & 0x00000100) {
+                                case    0x00000000: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_ADIW;
+                                    break;
+                                }
+                                case    0x00000100: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_SBIW;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case    0x00000800: {
+                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                    switch (opcode & 0x00000400) {
+                        case    0x00000000: {
+                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                            switch (opcode & 0x00000300) {
+                                case    0x00000000: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_CBI;
+                                    break;
+                                }
+                                case    0x00000100: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_SBIC;
+                                    break;
+                                }
+                                case    0x00000200: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_SBI;
+                                    break;
+                                }
+                                case    0x00000300: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_SBIS;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case    0x00000400: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_MUL;
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case    0x00002000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_IN;
+                    break;
+                }
+                case    0x00002800: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_OUT;
+                    break;
+                }
+            }
+            break;
+        }
+        case    0x0000c000: {
+            uint32_t    opcode  = get_opcode(code, 0, 16);
+            switch (opcode & 0x00002000) {
+                case    0x00000000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_RJMP;
+                    break;
+                }
+                case    0x00002000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_LDI;
+                    break;
+                }
+            }
+            break;
+        }
+        case    0x0000d000: {
+            uint32_t    opcode  = get_opcode(code, 0, 16);
+            switch (opcode & 0x00002000) {
+                case    0x00000000: {
+                    *length = 16;
+                    *translate = (translate_function_t)&avr_translate_RCALL;
+                    break;
+                }
+                case    0x00002000: {
+                    uint32_t    opcode  = get_opcode(code, 0, 16);
+                    switch (opcode & 0x00000c00) {
+                        case    0x00000000: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_BRBS;
+                            break;
+                        }
+                        case    0x00000400: {
+                            *length = 16;
+                            *translate = (translate_function_t)&avr_translate_BRBC;
+                            break;
+                        }
+                        case    0x00000800: {
+                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                            switch (opcode & 0x00000200) {
+                                case    0x00000000: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_BLD;
+                                    break;
+                                }
+                                case    0x00000200: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_BST;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                        case    0x00000c00: {
+                            uint32_t    opcode  = get_opcode(code, 0, 16);
+                            switch (opcode & 0x00000200) {
+                                case    0x00000000: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_SBRC;
+                                    break;
+                                }
+                                case    0x00000200: {
+                                    *length = 16;
+                                    *translate = (translate_function_t)&avr_translate_SBRS;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    break;
+                }
+            }
+            break;
+        }
+    }
+    return  0;
+}
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH 8/9] adding instruction translations
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
                   ` (5 preceding siblings ...)
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 7/9] adding instruction decoder Michael Rolnik
@ 2016-05-30  1:23 ` Michael Rolnik
  2016-06-02  6:44   ` Richard Henderson
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 9/9] updating gen_intermediate_code function to use prevously added decoder and translator Michael Rolnik
  2016-06-02  6:39 ` [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Richard Henderson
  8 siblings, 1 reply; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-avr/translate.c.inc | 2546 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 2546 insertions(+)
 create mode 100644 target-avr/translate.c.inc

diff --git a/target-avr/translate.c.inc b/target-avr/translate.c.inc
new file mode 100644
index 0000000..74b3c2c
--- /dev/null
+++ b/target-avr/translate.c.inc
@@ -0,0 +1,2546 @@
+/*
+ *  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 <stdio.h>
+#include <stdint.h>
+
+#ifdef  HOST_WORDS_BIGENDIAN
+#include "inst-be.h"
+#else
+#include "inst-le.h"
+#endif
+
+/*
+    NOTE:   all registers are assumed to hold 8 bit values.
+            so all operations done on registers should preseve this property
+*/
+
+/*
+    NOTE:   the flags C,H,V,N,V have either 0 or 1 values
+    NOTE:   the flag Z has inverse logic, when the value of Zf is 0 the flag is assumed to be set, non zero - not set
+*/
+
+void    gen_add_CHf(    TCGv    R, TCGv    Rd, TCGv    Rr);
+void    gen_add_Vf(     TCGv    R, TCGv    Rd, TCGv    Rr);
+void    gen_sub_CHf(    TCGv    R, TCGv    Rd, TCGv    Rr);
+void    gen_sub_Vf(     TCGv    R, TCGv    Rd, TCGv    Rr);
+void    gen_ZNSf(       TCGv    R);
+void    gen_push_ret(   CPUAVRState *env, int    ret);
+void    gen_pop_ret(    CPUAVRState *env, TCGv    ret);
+void    gen_jmp_ez(     void);
+void    gen_jmp_z(      void);
+
+void    gen_set_addr(   TCGv addr, TCGv H, TCGv M, TCGv l); /*  H:M:L   = addr  */
+void    gen_set_xaddr(  TCGv addr);
+void    gen_set_yaddr(  TCGv addr);
+void    gen_set_zaddr(  TCGv addr);
+
+TCGv    gen_get_addr(   TCGv H, TCGv M, TCGv L);            /*  addr = H:M:L    */
+TCGv    gen_get_xaddr(  void);
+TCGv    gen_get_yaddr(  void);
+TCGv    gen_get_zaddr(  void);
+int     sex(int Imm, unsigned bits);
+
+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_not_tl( t2,     R);             /*  t2  = Rd & ~R  */
+    tcg_gen_and_tl( t2,     Rd,     t2);
+    tcg_gen_not_tl( t3,     R);             /*  t3  = Rr  *~R  */
+    tcg_gen_and_tl( t3,     Rr,     t3);
+    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);
+}
+
+void    gen_add_Vf(TCGv    R, TCGv    Rd, TCGv    Rr)
+{
+    TCGv    t1      = tcg_temp_new_i32();
+    TCGv    t2      = tcg_temp_new_i32();
+
+    tcg_gen_not_tl( t1,     Rd);            /*  t1  = ~Rd & ~Rr & R  */
+    tcg_gen_not_tl( t2,     Rr);
+    tcg_gen_and_tl( t1,     t1,     t2);
+    tcg_gen_and_tl( t1,     t1,     R);
+
+    tcg_gen_not_tl( t2,     R);             /*  t2  = Rd & Rr & ~R  */
+    tcg_gen_and_tl( t2,     t2,     Rd);
+    tcg_gen_and_tl( t2,     t2,     Rr);
+
+    tcg_gen_or_tl(  t1,     t1,     t2);    /*  t1  = Rd & Rr & ~R | ~Rd & ~Rr & R  */
+
+    tcg_gen_shri_tl(cpu_Vf, t1,     7);     /*  Vf  = t1(7)  */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+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);
+}
+
+void    gen_sub_Vf(TCGv    R, TCGv    Rd, TCGv    Rr)
+{
+    TCGv    t1      = tcg_temp_new_i32();
+    TCGv    t2      = tcg_temp_new_i32();
+
+    /*  Vf  */
+    tcg_gen_and_tl( t1,     Rr,     R);     /*  t1  = Rd & ~Rr & ~R  */
+    tcg_gen_not_tl( t1,     t1);
+    tcg_gen_and_tl( t1,     t1,     Rd);
+    tcg_gen_not_tl( t2,     Rd);            /*  t2  = ~Rd & Rr & R  */
+    tcg_gen_and_tl( t2,     t2,     Rr);
+    tcg_gen_and_tl( t2,     t2,     R);
+    tcg_gen_or_tl(  t1,     t1,     t2);    /*  t1  = Rd & ~Rr & ~R | ~Rd & Rr & R  */
+    tcg_gen_shri_tl(cpu_Vf, t1,     7);     /*  Vf  = t1(7)  */
+
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(t1);
+}
+
+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_and_tl( cpu_Sf, cpu_Nf, cpu_Vf);/*  Sf  = Nf & Vf  */
+}
+
+void    gen_push_ret(   CPUAVRState *env, int    ret)
+{
+    tcg_gen_qemu_st8(   tcg_const_local_i32((ret & 0x0000ff)),      cpu_sp, DATA_INDEX);
+    tcg_gen_subi_tl(    cpu_sp, cpu_sp, 1);
+
+    if (   avr_feature(env, AVR_FEATURE_2_BYTE_PC)
+        || avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+        tcg_gen_qemu_st8(   tcg_const_local_i32((ret & 0x00ff00) >> 8), cpu_sp, DATA_INDEX);
+        tcg_gen_subi_tl(    cpu_sp, cpu_sp, 1);
+    }
+
+    if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+        tcg_gen_qemu_st8(   tcg_const_local_i32((ret & 0xff0000) >> 16),cpu_sp, DATA_INDEX);
+        tcg_gen_subi_tl(    cpu_sp, cpu_sp, 1);
+    }
+}
+
+void    gen_pop_ret(    CPUAVRState *env, TCGv    ret)
+{
+    TCGv    t0  = tcg_const_i32(0);
+    TCGv    t1  = tcg_const_i32(0);
+    TCGv    t2  = tcg_const_i32(0);
+
+    if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+        tcg_gen_addi_tl(    cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_ld8u(  t2,     cpu_sp, DATA_INDEX);
+        tcg_gen_shli_tl(    t2,     t2,     16);
+    }
+
+    if (    avr_feature(env, AVR_FEATURE_2_BYTE_PC)
+        ||  avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
+        tcg_gen_addi_tl(    cpu_sp, cpu_sp, 1);
+        tcg_gen_qemu_ld8u(  t1,     cpu_sp, DATA_INDEX);
+        tcg_gen_shli_tl(    t1,     t1,     8);
+    }
+
+    tcg_gen_addi_tl(    cpu_sp, cpu_sp, 1);
+    tcg_gen_qemu_ld8u(  t0,     cpu_sp, DATA_INDEX);
+
+    tcg_gen_or_tl(      ret,    t0,     t1);
+    tcg_gen_or_tl(      ret,    ret,    t2);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t2);
+}
+
+void    gen_jmp_ez()
+{
+    tcg_gen_mov_tl(     cpu_pc, cpu_eind);
+    tcg_gen_shli_tl(    cpu_pc, cpu_pc, 8);
+    tcg_gen_or_tl(      cpu_pc, cpu_pc, cpu_r[31]);
+    tcg_gen_shli_tl(    cpu_pc, cpu_pc, 8);
+    tcg_gen_or_tl(      cpu_pc, cpu_pc, cpu_r[30]);
+    tcg_gen_andi_tl(    cpu_pc, cpu_pc, 0xffffff);
+    tcg_gen_exit_tb(0);
+}
+
+void    gen_jmp_z()
+{
+    tcg_gen_mov_tl(     cpu_pc, cpu_r[31]);
+    tcg_gen_shli_tl(    cpu_pc, cpu_pc, 8);
+    tcg_gen_or_tl(      cpu_pc, cpu_pc, cpu_r[30]);
+    tcg_gen_andi_tl(    cpu_pc, cpu_pc, 0xffff);
+    tcg_gen_exit_tb(0);
+}
+
+void    gen_set_addr( TCGv addr, TCGv H, TCGv M, TCGv L)
+{
+    tcg_gen_andi_tl(L,      addr,   0xff);
+
+    tcg_gen_shri_tl(addr,   addr,   8);
+    tcg_gen_andi_tl(M,      addr,   0xff);
+
+    tcg_gen_shri_tl(addr,   addr,   8);
+    tcg_gen_andi_tl(H,      addr,   0xff);
+}
+
+void    gen_set_xaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampX, cpu_r[27], cpu_r[26]);
+}
+
+void    gen_set_yaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampY, cpu_r[29], cpu_r[28]);
+}
+
+void    gen_set_zaddr(TCGv addr)
+{
+    gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]);
+}
+
+TCGv    gen_get_addr(TCGv H, TCGv M, TCGv L)
+{
+    TCGv    addr= tcg_temp_new_i32();
+
+    tcg_gen_mov_tl( addr,   H);                     /*  addr    = H:M:L  */
+    tcg_gen_shli_tl(addr,   addr,   8);
+    tcg_gen_or_tl(  addr,   addr,   M);
+    tcg_gen_shli_tl(addr,   addr,   8);
+    tcg_gen_or_tl(  addr,   addr,   L);
+
+    return  addr;
+}
+
+TCGv    gen_get_xaddr()
+{
+    return  gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]);
+}
+
+TCGv    gen_get_yaddr()
+{
+    return  gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
+}
+
+TCGv    gen_get_zaddr()
+{
+    return  gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
+}
+
+int     sex(int Imm, unsigned bits)
+{
+    Imm <<= 32 - bits;
+    Imm >>= 32 - bits;
+
+    return  Imm;
+}
+
+/*
+    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,
+                                         avr_opcode_ADC_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    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,
+                                         avr_opcode_ADD_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    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,
+                                         avr_opcode_ADIW_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_ADIW_SBIW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    RdL = cpu_r[24 + 2  *inst->Rd];
+    TCGv    RdH = cpu_r[25 + 2  *inst->Rd];
+    int     Imm = (inst->hImm << 4) | (inst->lImm);
+    TCGv    R   = tcg_temp_new_i32();
+    TCGv    Rd  = tcg_temp_new_i32();
+    TCGv    t0  = tcg_temp_new_i32();
+
+    /*  op  */
+    tcg_gen_shli_tl(Rd,     RdH,    8);     /*  R = ((H << 8) | L) + Imm  */
+    tcg_gen_or_tl(  Rd,     RdL,    Rd);
+    tcg_gen_addi_tl(R,      Rd,     Imm);
+    tcg_gen_andi_tl(R,      R,      0xffff);/*  make it 16 bits  */
+
+    /*  Cf  */
+    tcg_gen_not_tl( t0,     R);             /*  t0  = Rd & ~R  */
+    tcg_gen_and_tl( t0,     Rd,     t0);
+    tcg_gen_shri_tl(cpu_Cf, t0,     15);    /*  Cf  = t0(15)  */
+
+    /*  Vf  */
+    tcg_gen_not_tl( t0,     Rd);            /*  t0  = ~Rd & R  */
+    tcg_gen_and_tl( t0,     R,      t0);
+
+    tcg_gen_shri_tl(cpu_Vf, t0,     15);    /*  Vf  = t0(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_and_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(t0);
+    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,
+                                         avr_opcode_AND_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    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,
+                                         avr_opcode_ANDI_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    int     Imm = (inst->hImm << 4) | (inst->lImm);
+
+    /*  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,
+                                         avr_opcode_ASR_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    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,
+                                         avr_opcode_BCLR_t const *inst)
+{
+    switch(inst->Bit) {
+        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,
+                                         avr_opcode_BLD_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    t1  = tcg_temp_new_i32();
+
+    tcg_gen_shli_tl(t1,     cpu_Tf, inst->Bit);
+    tcg_gen_or_tl(  Rd,     Rd,     t1);
+    tcg_gen_and_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,
+                                         avr_opcode_BRBC_t const *inst)
+{
+    TCGLabel   *taken   = gen_new_label();
+    int         Imm     = sex(inst->Imm, 7);
+
+    switch(inst->Bit) {
+        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,
+                                         avr_opcode_BRBS_t const *inst)
+{
+    TCGLabel   *taken   = gen_new_label();
+    int         Imm     = sex(inst->Imm, 7);
+
+    switch(inst->Bit) {
+        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,
+                                         avr_opcode_BSET_t const *inst)
+{
+    switch(inst->Bit) {
+        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,
+                                         avr_opcode_BREAK_t const *inst)
+{
+    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,
+                                         avr_opcode_BST_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+
+    tcg_gen_andi_tl(cpu_Tf, Rd,     1 << inst->Bit);
+    tcg_gen_shri_tl(cpu_Tf, cpu_Tf, inst->Bit);
+
+    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,
+                                         avr_opcode_CALL_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_JMP_CALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    int     Imm = (inst->hImm << 17) | inst->lImm;
+    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,
+                                         avr_opcode_CBI_t const *inst)
+{
+    TCGv    data= cpu_io[inst->Imm];
+    TCGv    port= tcg_const_i32(inst->Imm);
+
+    tcg_gen_andi_tl(data,   data,   ~(1 << inst->Bit));
+    gen_helper_outb(cpu_env,port,   data);
+
+    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,
+                                         avr_opcode_COM_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    R   = tcg_temp_new_i32();
+
+    tcg_gen_movi_tl(R,      0xff);
+    tcg_gen_sub_tl( Rd,     R,      Rd);
+
+    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,
+                                         avr_opcode_CP_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    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,
+                                         avr_opcode_CPC_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    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);
+
+    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,
+                                         avr_opcode_CPI_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    int     Imm = (inst->hImm << 4) | inst->lImm;
+    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);
+
+    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,
+                                         avr_opcode_CPSE_t const *inst)
+{
+    TCGv        Rd  = cpu_r[inst->Rd];
+    TCGv        Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    TCGLabel   *skip= gen_new_label();
+
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[1].npc);      /*  PC if next inst is skipped  */
+    tcg_gen_brcond_i32( TCG_COND_EQ, Rd, Rr, skip);
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[0].npc);      /*  PC if next inst is not skipped  */
+    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,
+                                         avr_opcode_DEC_t const *inst)
+{
+    TCGv        Rd  = cpu_r[inst->Rd];
+
+    tcg_gen_subi_tl(Rd,     Rd,     1);     /*  Rd  = Rd - 1  */
+    tcg_gen_andi_tl(Rd,     Rd,     0xff);  /*  make it 8 bits  */
+
+    tcg_gen_setcondi_tl(    TCG_COND_EQ,    cpu_Vf,     Rd,     0x7f);  /* 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,
+                                         avr_opcode_DES_t const *inst)
+{
+    /*  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,
+                                         avr_opcode_EICALL_t const *inst)
+{
+    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,
+                                         avr_opcode_EIJMP_t const *inst)
+{
+    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,
+                                         avr_opcode_ELPM1_t const *inst)
+{
+    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,   CODE_INDEX);    /*  Rd      = mem[addr]  */
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_ELPM2(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_ELPM2_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_ELPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(Rd,   addr,   CODE_INDEX);    /*  Rd      = mem[addr]  */
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_ELPMX(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_ELPMX_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_ELPMX) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(Rd,   addr,   CODE_INDEX);    /*  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,
+                                         avr_opcode_EOR_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    TCGv    R   = tcg_temp_new_i32();
+
+    tcg_gen_xor_tl( R,      Rd,     Rr);
+
+    tcg_gen_movi_tl(cpu_Vf, 0);
+    gen_ZNSf(R);
+
+    tcg_temp_free_i32(R);
+
+    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,
+                                         avr_opcode_FMUL_t const *inst)
+{
+    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 + inst->Rd];
+    TCGv    Rr  = cpu_r[16 + inst->Rr];
+    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,
+                                         avr_opcode_FMULS_t const *inst)
+{
+    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 + inst->Rd];
+    TCGv    Rr  = cpu_r[16 + inst->Rr];
+    TCGv    R   = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(   Rd, Rd);            /*  make Rd full 32 bit signed  */
+    tcg_gen_ext8s_tl(   Rr, Rr);            /*  make Rr full 32 bit signed  */
+    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_FMULSU(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_FMULSU_t const *inst)
+{
+    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 + inst->Rd];
+    TCGv    Rr  = cpu_r[16 + inst->Rr];
+    TCGv    R   = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(   Rd, Rd);            /*  make Rd full 32 bit signed  */
+    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);
+
+    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,
+                                         avr_opcode_ICALL_t const *inst)
+{
+    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,
+                                         avr_opcode_IJMP_t const *inst)
+{
+    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,
+                                         avr_opcode_IN_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    int     Imm = (inst->hImm << 4) | inst->lImm;
+    TCGv    port= tcg_const_i32(Imm);
+    TCGv    data= cpu_io[Imm];
+
+    gen_helper_inb( data,   cpu_env,port);
+    tcg_gen_mov_tl( Rd,     data);
+
+    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,
+                                         avr_opcode_INC_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+
+    tcg_gen_addi_tl(Rd,     Rd,     1);
+    tcg_gen_andi_tl(Rd,     Rd,     0xff);
+
+    tcg_gen_setcondi_tl(    TCG_COND_EQ,    cpu_Vf,     Rd,     0x80);  /* 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,
+                                         avr_opcode_JMP_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_JMP_CALL) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    gen_goto_tb(env, ctx, 0, (inst->hImm << 17) | inst->lImm);
+    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.
+*/
+int     avr_translate_LAC(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_LAC_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    Rr  = cpu_r[inst->Rr];
+    TCGv    addr= gen_get_zaddr();
+    TCGv    t0  = tcg_temp_new_i32();
+    TCGv    t1  = tcg_temp_new_i32();
+
+    tcg_gen_qemu_ld8u(
+                    t0,     addr,   DATA_INDEX);    /*  t0      = mem[addr]  */
+    tcg_gen_movi_tl(t1,     0xff);                  /*  t1      = t0 & (0xff - Rr)  */
+    tcg_gen_sub_tl( t1,     t1,     Rr);
+    tcg_gen_and_tl( t1,     t0,     t1);
+
+    tcg_gen_mov_tl( Rr,     t0);                    /*  Rr      = t0  */
+    tcg_gen_qemu_st8(   t1, addr,   DATA_INDEX);    /*  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,
+                                         avr_opcode_LAS_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    Rr  = cpu_r[inst->Rr];
+    TCGv    addr= gen_get_zaddr();
+    TCGv    t0  = tcg_temp_new_i32();
+    TCGv    t1  = tcg_temp_new_i32();
+
+    tcg_gen_qemu_ld8u(
+                    t0,     addr,   DATA_INDEX);    /*  t0      = mem[addr]  */
+    tcg_gen_or_tl(  t1,     t0,     Rr);
+
+    tcg_gen_mov_tl( Rr,     t0);                    /*  Rr      = t0  */
+    tcg_gen_qemu_st8(   t1, addr,   DATA_INDEX);    /*  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,
+                                         avr_opcode_LAT_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    Rr   = cpu_r[inst->Rr];
+    TCGv    addr = gen_get_zaddr();
+    TCGv    t0   = tcg_temp_new_i32();
+    TCGv    t1   = tcg_temp_new_i32();
+
+    tcg_gen_qemu_ld8u(
+                    t0,     addr,   DATA_INDEX);    /*  t0      = mem[addr]  */
+    tcg_gen_xor_tl( t1,     t0,     Rr);
+
+    tcg_gen_mov_tl( Rr,     t0);                    /*  Rr      = t0  */
+    tcg_gen_qemu_st8(   t1, addr,   DATA_INDEX);    /*  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,
+                                         avr_opcode_LDX1_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_xaddr();
+
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_LDX2(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_LDX2_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_xaddr();
+
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+    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,
+                                         avr_opcode_LDX3_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_xaddr();
+
+    tcg_gen_subi_tl(addr,   addr,   1);             /*  addr    = addr - 1  */
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+    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,
+                                         avr_opcode_LDY2_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_yaddr();
+
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+    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,
+                                         avr_opcode_LDY3_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_yaddr();
+
+    tcg_gen_subi_tl(addr,   addr,   1);             /*  addr    = addr - 1  */
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_LDDY(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_LDDY_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_yaddr();
+
+    tcg_gen_addi_tl(addr,   addr,   (inst->hImm << 5) | (inst->mImm << 2) | inst->lImm);
+                                                    /*  addr    = addr + q  */
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+
+    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,
+                                         avr_opcode_LDZ2_t const *inst)
+{
+    TCGv    Rd      = cpu_r[inst->Rd];
+    TCGv    addr    = gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+    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,
+                                         avr_opcode_LDZ3_t const *inst)
+{
+    TCGv    Rd      = cpu_r[inst->Rd];
+    TCGv    addr    = gen_get_zaddr();
+
+    tcg_gen_subi_tl(addr,   addr,   1);             /*  addr    = addr - 1  */
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_LDDZ(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_LDDZ_t const *inst)
+{
+    TCGv    Rd      = cpu_r[inst->Rd];
+    TCGv    addr    = gen_get_zaddr();
+
+    tcg_gen_addi_tl(addr,   addr,   (inst->hImm << 5) | (inst->mImm << 2) | inst->lImm);
+                                                    /*  addr    = addr + q  */
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+
+    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,
+                                         avr_opcode_LDI_t const *inst)
+{
+    TCGv    Rd  = cpu_r[16 + inst->Rd];
+    int     imm = (inst->hImm << 4) | inst->lImm;
+
+    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,
+                                         avr_opcode_LDS_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    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,   inst->Imm);
+
+    tcg_gen_qemu_ld8u(
+                    Rd,     addr,   DATA_INDEX);
+
+    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,
+                                         avr_opcode_LPM1_t const *inst)
+{
+    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,   CODE_INDEX);    /*  Rd      = mem[addr]  */
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_LPM2(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_LPM2_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_LPM) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    Rd  = cpu_r[inst->Rd];
+    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,   CODE_INDEX);    /*  Rd      = mem[addr]  */
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_LPMX(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_LPMX_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_LPMX) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    Rd  = cpu_r[inst->Rd];
+    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,   CODE_INDEX);    /*  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,
+                                         avr_opcode_LSR_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+
+    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,
+                                         avr_opcode_MOV_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+
+    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,
+                                         avr_opcode_MOVW_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_MOVW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    RdL = cpu_r[inst->Rd  *2 + 0];
+    TCGv    RdH = cpu_r[inst->Rd  *2 + 1];
+    TCGv    RrL = cpu_r[inst->Rr  *2 + 0];
+    TCGv    RrH = cpu_r[inst->Rr  *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,
+                                         avr_opcode_MUL_t const *inst)
+{
+    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[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | inst->lRr];
+    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,
+                                         avr_opcode_MULS_t const *inst)
+{
+    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 + inst->Rd];
+    TCGv    Rr  = cpu_r[16 + inst->Rr];
+    TCGv    R   = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(   Rd, Rd);            /*  make Rd full 32 bit signed  */
+    tcg_gen_ext8s_tl(   Rr, Rr);            /*  make Rr full 32 bit signed  */
+    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_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(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,
+                                         avr_opcode_MULSU_t const *inst)
+{
+    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 + inst->Rd];
+    TCGv    Rr  = cpu_r[16 + inst->Rr];
+    TCGv    R   = tcg_temp_new_i32();
+
+    tcg_gen_ext8s_tl(   Rd, Rd);            /*  make Rd full 32 bit signed  */
+    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_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(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,
+                                         avr_opcode_NEG_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    R   = tcg_temp_new_i32();
+
+    tcg_gen_neg_tl( R,      Rd);
+
+    tcg_gen_setcondi_tl(TCG_COND_NE,cpu_Cf,     R,      0x00);  /*  Cf  = R != 0x00  */
+    tcg_gen_setcondi_tl(TCG_COND_EQ,cpu_Vf,     R,      0x80);  /*  Vf  = R == 0x80  */
+    tcg_gen_not_tl( cpu_Hf, Rd);                                /*  Hf  = (~Rd | R)(3)  */
+    tcg_gen_or_tl(  cpu_Hf, cpu_Hf, R);
+    tcg_gen_shri_tl(cpu_Hf, cpu_Hf, 3);
+    tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
+    gen_ZNSf(       R);
+
+    tcg_temp_free_i32(R);
+
+    return  BS_NONE;
+}
+
+/*
+    This instruction performs a single cycle No Operation.
+*/
+int     avr_translate_NOP(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_NOP_t const *inst)
+{
+
+    /*  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,
+                                         avr_opcode_OR_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    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,
+                                         avr_opcode_ORI_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    int     Imm = (inst->hImm << 4) | (inst->lImm);
+
+    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,
+                                         avr_opcode_OUT_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    int     Imm = (inst->hImm << 4) | inst->lImm;
+    TCGv    port= tcg_const_i32(Imm);
+    TCGv    data= cpu_io[Imm];
+
+    tcg_gen_mov_tl( data,   Rd);
+    gen_helper_outb(cpu_env,port,   data);
+
+    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,
+                                         avr_opcode_POP_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+
+    tcg_gen_addi_tl(cpu_sp, cpu_sp,     1);
+    tcg_gen_qemu_ld8u(
+                    Rd,     cpu_sp,     DATA_INDEX);
+
+    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,
+                                         avr_opcode_PUSH_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+
+    tcg_gen_qemu_st8(
+                    Rd,     cpu_sp,     DATA_INDEX);
+    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,
+                                         avr_opcode_RCALL_t const *inst)
+{
+    int ret = ctx->inst[0].npc;
+    int dst = ctx->inst[0].npc + sex(inst->Imm, 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,
+                                         avr_opcode_RET_t const *inst)
+{
+    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,
+                                         avr_opcode_RETI_t const *inst)
+{
+    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,
+                                         avr_opcode_RJMP_t const *inst)
+{
+    int dst = ctx->inst[0].npc + sex(inst->Imm, 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,
+                                         avr_opcode_ROR_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    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,
+                                         avr_opcode_SBC_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    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,
+                                         avr_opcode_SBCI_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = tcg_const_i32((inst->hImm << 4) | inst->lImm);
+    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;
+}
+
+/*
+    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,
+                                         avr_opcode_SBI_t const *inst)
+{
+    TCGv    data    = cpu_io[inst->Imm];
+    TCGv    port    = tcg_const_i32(inst->Imm);
+
+    tcg_gen_ori_tl( data,   data,   1 << inst->Bit);
+    gen_helper_outb(cpu_env,port,   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,
+                                         avr_opcode_SBIC_t const *inst)
+{
+    TCGv        io  = cpu_io[inst->Imm];
+    TCGv        t0  = tcg_temp_new_i32();
+    TCGLabel   *skip= gen_new_label();
+
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[1].npc);      /*  PC if next inst is skipped  */
+    tcg_gen_andi_tl(    t0,     io,     1 << inst->Bit);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, skip);
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[0].npc);      /*  PC if next inst is not skipped  */
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(t0);
+
+    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,
+                                         avr_opcode_SBIS_t const *inst)
+{
+    TCGv        io  = cpu_io[inst->Imm];
+    TCGv        t0  = tcg_temp_new_i32();
+    TCGLabel   *skip= gen_new_label();
+
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[1].npc);  /*  PC if next inst is skipped  */
+    tcg_gen_andi_tl(    t0,     io,     1 << inst->Bit);
+    tcg_gen_brcondi_i32(TCG_COND_NE,    t0, 0, skip);
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[0].npc);  /*  PC if next inst is not skipped  */
+    gen_set_label(skip);
+
+    tcg_temp_free_i32(t0);
+
+    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,
+                                         avr_opcode_SBIW_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_ADIW_SBIW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    RdL = cpu_r[24 + 2  *inst->Rd];
+    TCGv    RdH = cpu_r[25 + 2  *inst->Rd];
+    int     Imm = (inst->hImm << 4) | (inst->lImm);
+    TCGv    R   = tcg_temp_new_i32();
+    TCGv    Rd  = tcg_temp_new_i32();
+    TCGv    t0  = tcg_temp_new_i32();
+
+    /*  op  */
+    tcg_gen_shli_tl(Rd,     RdH,    8);     /*  R = ((H << 8) | L) - Imm  */
+    tcg_gen_or_tl(  Rd,     RdL,    Rd);
+    tcg_gen_subi_tl(R,      Rd,     Imm);
+    tcg_gen_andi_tl(R,      R,      0xffff);/*  make it 16 bits  */
+
+    /*  Cf  */
+    tcg_gen_not_tl( t0,     R);             /*  t0  = Rd & ~R  */
+    tcg_gen_and_tl( t0,     Rd,     t0);
+    tcg_gen_shri_tl(cpu_Cf, t0,     15);    /*  Cf  = t0(15)  */
+
+    /*  Vf  */
+    tcg_gen_not_tl( t0,     Rd);            /*  t0  = ~Rd & R  */
+    tcg_gen_and_tl( t0,     R,      t0);
+
+    tcg_gen_shri_tl(cpu_Vf, t0,     15);    /*  Vf  = t0(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_and_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(t0);
+    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,
+                                         avr_opcode_SBRC_t const *inst)
+{
+    TCGv        Rr  = cpu_r[inst->Rr];
+    TCGv        t0  = tcg_temp_new_i32();
+    TCGLabel   *skip= gen_new_label();
+
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[1].npc);      /*  PC if next inst is skipped  */
+    tcg_gen_andi_tl(    t0,     Rr,     1 << inst->Bit);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, skip);
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[0].npc);  /*  PC if next inst is not skipped  */
+    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,
+                                         avr_opcode_SBRS_t const *inst)
+{
+    TCGv        Rr  = cpu_r[inst->Rr];
+    TCGv        t0  = tcg_temp_new_i32();
+    TCGLabel   *skip= gen_new_label();
+
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[1].npc);  /*  PC if next inst is skipped  */
+    tcg_gen_andi_tl(    t0,     Rr,     1 << inst->Bit);
+    tcg_gen_brcondi_i32(TCG_COND_NE,    t0, 0, skip);
+    tcg_gen_movi_tl(    cpu_pc, ctx->inst[0].npc);  /*  PC if next inst is not skipped  */
+    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,
+                                         avr_opcode_SLEEP_t const *inst)
+{
+    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,
+                                         avr_opcode_SPM_t const *inst)
+{
+    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,
+                                         avr_opcode_SPMX_t const *inst)
+{
+    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,
+                                         avr_opcode_STX1_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rr];
+    TCGv    addr= gen_get_xaddr();
+
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_STX2(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_STX2_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rr];
+    TCGv    addr= gen_get_xaddr();
+
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+    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,
+                                         avr_opcode_STX3_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rr];
+    TCGv    addr= gen_get_xaddr();
+
+    tcg_gen_subi_tl(addr,   addr,   1);             /*  addr    = addr - 1  */
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+    gen_set_xaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_STY2(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_STY2_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_yaddr();
+
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+    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,
+                                         avr_opcode_STY3_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_yaddr();
+
+    tcg_gen_subi_tl(addr,   addr,   1);             /*  addr    = addr - 1  */
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+    gen_set_yaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_STDY(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_STDY_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    addr= gen_get_yaddr();
+
+    tcg_gen_addi_tl(addr,   addr,   (inst->hImm << 5) | (inst->mImm << 2) | inst->lImm);
+                                                    /*  addr    = addr + q  */
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_STZ2(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_STZ2_t const *inst)
+{
+    TCGv    Rd      = cpu_r[inst->Rd];
+    TCGv    addr    = gen_get_zaddr();
+
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+    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,
+                                         avr_opcode_STZ3_t const *inst)
+{
+    TCGv    Rd      = cpu_r[inst->Rd];
+    TCGv    addr    = gen_get_zaddr();
+
+    tcg_gen_subi_tl(addr,   addr,   1);             /*  addr    = addr - 1  */
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+
+    gen_set_zaddr(addr);
+
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
+int     avr_translate_STDZ(CPUAVRState *env, DisasContext *ctx,
+                                         avr_opcode_STDZ_t const *inst)
+{
+    TCGv    Rd      = cpu_r[inst->Rd];
+    TCGv    addr    = gen_get_zaddr();
+
+    tcg_gen_addi_tl(addr,   addr,   (inst->hImm << 5) | (inst->mImm << 2) | inst->lImm);
+                                                    /*  addr    = addr + q  */
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+
+    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,
+                                         avr_opcode_STS_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    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,   inst->Imm);
+
+    tcg_gen_qemu_st8(
+                    Rd,     addr,   DATA_INDEX);
+
+    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,
+                                         avr_opcode_SUB_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = cpu_r[(inst->hRr << 4) | (inst->lRr)];
+    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,
+                                         avr_opcode_SUBI_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    TCGv    Rr  = tcg_const_i32((inst->hImm << 4) | inst->lImm);
+    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,
+                                         avr_opcode_SWAP_t const *inst)
+{
+    TCGv    Rd  = cpu_r[inst->Rd];
+    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,
+                                         avr_opcode_WDR_t const *inst)
+{
+
+    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,
+                                         avr_opcode_XCH_t const *inst)
+{
+    if (avr_feature(env, AVR_FEATURE_RMW) == false) {
+        gen_helper_unsupported(cpu_env);
+
+        return BS_EXCP;
+    }
+
+    TCGv    Rd      = cpu_r[inst->Rd];
+    TCGv    t0      = tcg_temp_new_i32();
+    TCGv    addr    = gen_get_zaddr();
+
+    tcg_gen_qemu_ld8u(
+                    addr,   t0,     DATA_INDEX);
+    tcg_gen_qemu_st8(
+                    addr,   Rd,     DATA_INDEX);
+    tcg_gen_mov_tl( Rd,     t0);
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(addr);
+
+    return  BS_NONE;
+}
+
-- 
2.4.9 (Apple Git-60)

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

* [Qemu-devel] [PATCH 9/9] updating gen_intermediate_code function to use prevously added decoder and translator
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
                   ` (6 preceding siblings ...)
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 8/9] adding instruction translations Michael Rolnik
@ 2016-05-30  1:23 ` Michael Rolnik
  2016-06-02  6:39 ` [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Richard Henderson
  8 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-05-30  1:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Rolnik, Michael Rolnik

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-avr/Makefile.objs |  4 ++-
 target-avr/translate.c   | 91 +++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/target-avr/Makefile.objs b/target-avr/Makefile.objs
index c503546..bbd2409 100644
--- a/target-avr/Makefile.objs
+++ b/target-avr/Makefile.objs
@@ -1,3 +1,5 @@
-obj-y   += translate.o cpu.o helper.o
+obj-y   += translate.o helper.o cpu.o
 obj-y   += gdbstub.o
 obj-$(CONFIG_SOFTMMU) += machine.o
+
+obj-y   += decode.o
diff --git a/target-avr/translate.c b/target-avr/translate.c
index e98aaef..5a7436f 100644
--- a/target-avr/translate.c
+++ b/target-avr/translate.c
@@ -30,13 +30,32 @@
 #include "exec/helper-gen.h"
 #include "exec/log.h"
 
+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,
+                                    uint8_t const      *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 consequitive instructions   */
+
     /*Routine used to access memory */
     int                         memidx;
     int                         bstate;
@@ -144,6 +163,55 @@ static inline void  gen_goto_tb(CPUAVRState        *env,
     }
 }
 
+#include "translate.c.inc"
+
+typedef int (*translate_function_t)(
+                                    CPUAVRState        *env,
+                                    DisasContext       *ctx,
+                                    uint8_t const      *opcode);
+void                avr_decode(
+                                    uint32_t            pc,
+                                    uint32_t           *length,
+                                    uint8_t const      *code,
+                                    translate_function_t *translate);
+
+
+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;
+
+    /*  the following function looks onto the opcode as a string of bytes   */
+    avr_decode(inst->cpc, &inst->length, (uint8_t const *)&inst->opcode, &inst->translate);
+
+    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);
+    }
+}
+
+uint32_t    get_opcode(
+                                    uint8_t const      *code,
+                                    unsigned            bitBase,
+                                    unsigned            bitSize)
+{
+    return  *(uint16_t *)code;
+}
+
+
 /*generate intermediate code for basic block 'tb'.  */
 void                gen_intermediate_code(
                                 CPUAVRState        *env,
@@ -176,18 +244,21 @@ void                gen_intermediate_code(
     gen_tb_start(tb);
 
     /*  decode first instruction    */
-    cpc = pc_start;
-    npc = cpc + 1;
+    ctx.inst[0].cpc     = pc_start;
+    decode_opc(cpu, &ctx, &ctx.inst[0]);
     do {
-        /*  translate current instruction   */
+        /*  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++;
 
-        /*  just skip to next instruction   */
-        cpc++;
-        npc++;
-        ctx.bstate  = BS_NONE;
-
         if (unlikely(cpu_breakpoint_test(cs, cpc * 2, BP_ANY))) {
             tcg_gen_movi_i32(cpu_pc, cpc);
             gen_helper_debug(cpu_env);
@@ -199,6 +270,8 @@ void                gen_intermediate_code(
             goto done_generating;
         }
 
+        ctx.bstate  = ctx.inst[0].translate(env, &ctx, (uint8_t const *)&ctx.inst[0].opcode);
+
         if (num_insns >= max_insns) {
             break;      /* max translated instructions limit reached */
         }
@@ -208,6 +281,8 @@ void                gen_intermediate_code(
         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) {
-- 
2.4.9 (Apple Git-60)

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

* Re: [Qemu-devel] [PATCH 4/9] adding instructions encodings for LE and BE compilers.
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 4/9] adding instructions encodings for LE and BE compilers Michael Rolnik
@ 2016-06-02  6:32   ` Richard Henderson
  2016-06-02  6:40     ` Michael Rolnik
  0 siblings, 1 reply; 15+ messages in thread
From: Richard Henderson @ 2016-06-02  6:32 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel; +Cc: Michael Rolnik

On 05/29/2016 06:23 PM, Michael Rolnik wrote:
>     I am aware of bad portability of bit fields as compilers
>     for LE and BE hosts lists bit fields in different order
>     However they won't "parse" in target memory but a data prepared by me

What data prepared by you?  You're assigning to an int16_t and hoping that 
specific bit fields map to specific bits.  That's just non-portable.

We don't want code that does that.  The fact that you had to replicate 1018 
lines of code should have been a hint that you're doing it wrong.

Take Peter's advice and use extract32.


r~

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

* Re: [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions
  2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
                   ` (7 preceding siblings ...)
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 9/9] updating gen_intermediate_code function to use prevously added decoder and translator Michael Rolnik
@ 2016-06-02  6:39 ` Richard Henderson
  2016-06-02  6:41   ` Michael Rolnik
  8 siblings, 1 reply; 15+ messages in thread
From: Richard Henderson @ 2016-06-02  6:39 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel; +Cc: Michael Rolnik

On 05/29/2016 06:23 PM, Michael Rolnik wrote:
> +static void         avr_cpu_set_pc(
> +                                CPUState           *cs,
> +                                vaddr               value)

The formatting throughout all of these patches is wrong.
You need to follow the instructions in CODING_STYLE.
You can use ./scripts/checkpatch.pl to catch mistakes.


r~

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

* Re: [Qemu-devel] [PATCH 4/9] adding instructions encodings for LE and BE compilers.
  2016-06-02  6:32   ` Richard Henderson
@ 2016-06-02  6:40     ` Michael Rolnik
  0 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-06-02  6:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, Michael Rolnik, Michael Rolnik

I disagree. it's non portable as long as you don't know what compiler you
are using.
if bitfields are not acceptable at all, I will regenerate my code.

thanks.

On Thu, Jun 2, 2016 at 9:32 AM, Richard Henderson <rth@twiddle.net> wrote:

> On 05/29/2016 06:23 PM, Michael Rolnik wrote:
>
>>     I am aware of bad portability of bit fields as compilers
>>     for LE and BE hosts lists bit fields in different order
>>     However they won't "parse" in target memory but a data prepared by me
>>
>
> What data prepared by you?  You're assigning to an int16_t and hoping that
> specific bit fields map to specific bits.  That's just non-portable.
>
> We don't want code that does that.  The fact that you had to replicate
> 1018 lines of code should have been a hint that you're doing it wrong.
>
> Take Peter's advice and use extract32.
>
>
> r~
>



-- 
Best Regards,
Michael Rolnik

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

* Re: [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions
  2016-06-02  6:39 ` [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Richard Henderson
@ 2016-06-02  6:41   ` Michael Rolnik
  0 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-06-02  6:41 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, Michael Rolnik

I ran checkpatch.pl on my patches and it was ok.
I will fix it.

On Thu, Jun 2, 2016 at 9:39 AM, Richard Henderson <rth@twiddle.net> wrote:

> On 05/29/2016 06:23 PM, Michael Rolnik wrote:
>
>> +static void         avr_cpu_set_pc(
>> +                                CPUState           *cs,
>> +                                vaddr               value)
>>
>
> The formatting throughout all of these patches is wrong.
> You need to follow the instructions in CODING_STYLE.
> You can use ./scripts/checkpatch.pl to catch mistakes.
>
>
> r~
>



-- 
Best Regards,
Michael Rolnik

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

* Re: [Qemu-devel] [PATCH 8/9] adding instruction translations
  2016-05-30  1:23 ` [Qemu-devel] [PATCH 8/9] adding instruction translations Michael Rolnik
@ 2016-06-02  6:44   ` Richard Henderson
  2016-06-02  6:47     ` Michael Rolnik
  0 siblings, 1 reply; 15+ messages in thread
From: Richard Henderson @ 2016-06-02  6:44 UTC (permalink / raw)
  To: Michael Rolnik, qemu-devel; +Cc: Michael Rolnik

On 05/29/2016 06:23 PM, Michael Rolnik wrote:
> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
> ---
>  target-avr/translate.c.inc | 2546 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 2546 insertions(+)
>  create mode 100644 target-avr/translate.c.inc

Is there any good reason for you to pull out these functions into an include 
file?  I think this is simply confusing.


r~

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

* Re: [Qemu-devel] [PATCH 8/9] adding instruction translations
  2016-06-02  6:44   ` Richard Henderson
@ 2016-06-02  6:47     ` Michael Rolnik
  0 siblings, 0 replies; 15+ messages in thread
From: Michael Rolnik @ 2016-06-02  6:47 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, Michael Rolnik

right. no reason. I can make it just a C file.
when I started I was not sure what was the best way to do it as I generate
some come code.
thanks, I will fix it.

On Thu, Jun 2, 2016 at 9:44 AM, Richard Henderson <rth@twiddle.net> wrote:

> On 05/29/2016 06:23 PM, Michael Rolnik wrote:
>
>> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
>> ---
>>  target-avr/translate.c.inc | 2546
>> ++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 2546 insertions(+)
>>  create mode 100644 target-avr/translate.c.inc
>>
>
> Is there any good reason for you to pull out these functions into an
> include file?  I think this is simply confusing.
>
>
> r~
>



-- 
Best Regards,
Michael Rolnik

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

end of thread, other threads:[~2016-06-02  6:48 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-30  1:23 [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Michael Rolnik
2016-05-30  1:23 ` [Qemu-devel] [PATCH 2/9] adding AVR CPU features/flavors Michael Rolnik
2016-05-30  1:23 ` [Qemu-devel] [PATCH 3/9] adding a sample AVR board Michael Rolnik
2016-05-30  1:23 ` [Qemu-devel] [PATCH 4/9] adding instructions encodings for LE and BE compilers Michael Rolnik
2016-06-02  6:32   ` Richard Henderson
2016-06-02  6:40     ` Michael Rolnik
2016-05-30  1:23 ` [Qemu-devel] [PATCH 5/9] adding AVR interrupt handling Michael Rolnik
2016-05-30  1:23 ` [Qemu-devel] [PATCH 6/9] adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions Michael Rolnik
2016-05-30  1:23 ` [Qemu-devel] [PATCH 7/9] adding instruction decoder Michael Rolnik
2016-05-30  1:23 ` [Qemu-devel] [PATCH 8/9] adding instruction translations Michael Rolnik
2016-06-02  6:44   ` Richard Henderson
2016-06-02  6:47     ` Michael Rolnik
2016-05-30  1:23 ` [Qemu-devel] [PATCH 9/9] updating gen_intermediate_code function to use prevously added decoder and translator Michael Rolnik
2016-06-02  6:39 ` [Qemu-devel] [PATCH 1/9] AVR cores support is added. 1. basic CPU structure 2. registers 3. no instructions Richard Henderson
2016-06-02  6:41   ` 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.