diff mbox

[v14,2/9] target-avr: adding AVR CPU features/flavors

Message ID 1469806345-67852-3-git-send-email-mrolnik@gmail.com
State New
Headers show

Commit Message

Michael Rolnik July 29, 2016, 3:32 p.m. UTC
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
 target-avr/cpu.c     | 319 +++++++++++++++++++++++++++++++++++++++++++++++++--
 target-avr/cpu.h     |  52 ++++++++-
 target-avr/machine.c |  28 ++---
 3 files changed, 373 insertions(+), 26 deletions(-)

Comments

Peter Maydell Aug. 15, 2016, 3:31 p.m. UTC | #1
On 29 July 2016 at 16:32, Michael Rolnik <mrolnik@gmail.com> wrote:
> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
> ---
>  target-avr/cpu.c     | 319 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  target-avr/cpu.h     |  52 ++++++++-
>  target-avr/machine.c |  28 ++---
>  3 files changed, 373 insertions(+), 26 deletions(-)
>
> diff --git a/target-avr/cpu.c b/target-avr/cpu.c
> index c5ee2e9..fa15727 100644
> --- a/target-avr/cpu.c
> +++ b/target-avr/cpu.c
> @@ -203,9 +203,300 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
>      dc->cannot_destroy_with_object_finalize_yet = true;
>  }
>
> -static void avr_any_initfn(Object *obj)

Please don't add code in one patch and then remove it in the next.


> @@ -226,13 +531,7 @@ static gint avr_cpu_list_compare(gconstpointer a, gconstpointer 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);
> -    }
> +    return strcmp(name_a, name_b);
>  }

Ditto.

>
>  static void avr_cpu_list_entry(gpointer data, gpointer user_data)

> diff --git a/target-avr/machine.c b/target-avr/machine.c
> index 9f20aed..2b005cc 100644
> --- a/target-avr/machine.c
> +++ b/target-avr/machine.c
> @@ -44,8 +44,8 @@ static void put_sreg(QEMUFile *f, void *opaque, size_t size)
>
>  static const VMStateInfo vms_sreg = {
>      .name = "sreg",
> -    .get  = get_sreg,
> -    .put  = put_sreg,
> +    .get = get_sreg,
> +    .put = put_sreg,
>  };

Please don't add code in one patch and then change its formatting
in the next patch; just format it correctly to start with.

Otherwise this patch looks OK.

thanks
-- PMM
Michael Rolnik Aug. 15, 2016, 3:32 p.m. UTC | #2
Richard. Please stop reviewing it. It seems to be a wrong review.

On Mon, Aug 15, 2016, 6:31 PM Peter Maydell <peter.maydell@linaro.org>
wrote:

> On 29 July 2016 at 16:32, Michael Rolnik <mrolnik@gmail.com> wrote:
> > Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
> > ---
> >  target-avr/cpu.c     | 319
> +++++++++++++++++++++++++++++++++++++++++++++++++--
> >  target-avr/cpu.h     |  52 ++++++++-
> >  target-avr/machine.c |  28 ++---
> >  3 files changed, 373 insertions(+), 26 deletions(-)
> >
> > diff --git a/target-avr/cpu.c b/target-avr/cpu.c
> > index c5ee2e9..fa15727 100644
> > --- a/target-avr/cpu.c
> > +++ b/target-avr/cpu.c
> > @@ -203,9 +203,300 @@ static void avr_cpu_class_init(ObjectClass *oc,
> void *data)
> >      dc->cannot_destroy_with_object_finalize_yet = true;
> >  }
> >
> > -static void avr_any_initfn(Object *obj)
>
> Please don't add code in one patch and then remove it in the next.
>
>
> > @@ -226,13 +531,7 @@ static gint avr_cpu_list_compare(gconstpointer a,
> gconstpointer 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);
> > -    }
> > +    return strcmp(name_a, name_b);
> >  }
>
> Ditto.
>
> >
> >  static void avr_cpu_list_entry(gpointer data, gpointer user_data)
>
> > diff --git a/target-avr/machine.c b/target-avr/machine.c
> > index 9f20aed..2b005cc 100644
> > --- a/target-avr/machine.c
> > +++ b/target-avr/machine.c
> > @@ -44,8 +44,8 @@ static void put_sreg(QEMUFile *f, void *opaque, size_t
> size)
> >
> >  static const VMStateInfo vms_sreg = {
> >      .name = "sreg",
> > -    .get  = get_sreg,
> > -    .put  = put_sreg,
> > +    .get = get_sreg,
> > +    .put = put_sreg,
> >  };
>
> Please don't add code in one patch and then change its formatting
> in the next patch; just format it correctly to start with.
>
> Otherwise this patch looks OK.
>
> thanks
> -- PMM
>
diff mbox

Patch

diff --git a/target-avr/cpu.c b/target-avr/cpu.c
index c5ee2e9..fa15727 100644
--- a/target-avr/cpu.c
+++ b/target-avr/cpu.c
@@ -203,9 +203,300 @@  static void avr_cpu_class_init(ObjectClass *oc, void *data)
     dc->cannot_destroy_with_object_finalize_yet = true;
 }
 
-static void avr_any_initfn(Object *obj)
+static void avr_avr1_initfn(Object *obj)
 {
-    /* Set cpu feature flags */
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+}
+
+static void avr_avr2_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+}
+
+static void avr_avr25_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+}
+
+static void avr_avr3_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+}
+
+static void avr_avr31_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+}
+
+static void avr_avr35_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+}
+
+static void avr_avr4_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+}
+
+static void avr_avr5_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+}
+
+static void avr_avr51_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+}
+
+static void avr_avr6_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_3_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_EIJMP_EICALL);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+}
+
+static void avr_xmega2_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
+static void avr_xmega4_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
+static void avr_xmega5_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPD);
+    avr_set_feature(env, AVR_FEATURE_RAMPX);
+    avr_set_feature(env, AVR_FEATURE_RAMPY);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
+static void avr_xmega6_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_3_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_EIJMP_EICALL);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
+}
+
+static void avr_xmega7_initfn(Object *obj)
+{
+    AVRCPU *cpu = AVR_CPU(obj);
+    CPUAVRState *env = &cpu->env;
+
+    avr_set_feature(env, AVR_FEATURE_LPM);
+    avr_set_feature(env, AVR_FEATURE_IJMP_ICALL);
+    avr_set_feature(env, AVR_FEATURE_ADIW_SBIW);
+    avr_set_feature(env, AVR_FEATURE_SRAM);
+    avr_set_feature(env, AVR_FEATURE_BREAK);
+
+    avr_set_feature(env, AVR_FEATURE_3_BYTE_PC);
+    avr_set_feature(env, AVR_FEATURE_2_BYTE_SP);
+    avr_set_feature(env, AVR_FEATURE_RAMPD);
+    avr_set_feature(env, AVR_FEATURE_RAMPX);
+    avr_set_feature(env, AVR_FEATURE_RAMPY);
+    avr_set_feature(env, AVR_FEATURE_RAMPZ);
+    avr_set_feature(env, AVR_FEATURE_EIJMP_EICALL);
+    avr_set_feature(env, AVR_FEATURE_ELPMX);
+    avr_set_feature(env, AVR_FEATURE_ELPM);
+    avr_set_feature(env, AVR_FEATURE_JMP_CALL);
+    avr_set_feature(env, AVR_FEATURE_LPMX);
+    avr_set_feature(env, AVR_FEATURE_MOVW);
+    avr_set_feature(env, AVR_FEATURE_MUL);
+    avr_set_feature(env, AVR_FEATURE_RMW);
 }
 
 typedef struct AVRCPUInfo {
@@ -214,7 +505,21 @@  typedef struct AVRCPUInfo {
 } AVRCPUInfo;
 
 static const AVRCPUInfo avr_cpus[] = {
-    {   .name = "any",      .initfn = avr_any_initfn },
+    {.name = "avr1", .initfn = avr_avr1_initfn},
+    {.name = "avr2", .initfn = avr_avr2_initfn},
+    {.name = "avr25", .initfn = avr_avr25_initfn},
+    {.name = "avr3", .initfn = avr_avr3_initfn},
+    {.name = "avr31", .initfn = avr_avr31_initfn},
+    {.name = "avr35", .initfn = avr_avr35_initfn},
+    {.name = "avr4", .initfn = avr_avr4_initfn},
+    {.name = "avr5", .initfn = avr_avr5_initfn},
+    {.name = "avr51", .initfn = avr_avr51_initfn},
+    {.name = "avr6", .initfn = avr_avr6_initfn},
+    {.name = "xmega2", .initfn = avr_xmega2_initfn},
+    {.name = "xmega4", .initfn = avr_xmega4_initfn},
+    {.name = "xmega5", .initfn = avr_xmega5_initfn},
+    {.name = "xmega6", .initfn = avr_xmega6_initfn},
+    {.name = "xmega7", .initfn = avr_xmega7_initfn},
 };
 
 static gint avr_cpu_list_compare(gconstpointer a, gconstpointer b)
@@ -226,13 +531,7 @@  static gint avr_cpu_list_compare(gconstpointer a, gconstpointer 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);
-    }
+    return strcmp(name_a, name_b);
 }
 
 static void avr_cpu_list_entry(gpointer data, gpointer user_data)
diff --git a/target-avr/cpu.h b/target-avr/cpu.h
index 0cff5f7..9ef8c41 100644
--- a/target-avr/cpu.h
+++ b/target-avr/cpu.h
@@ -83,6 +83,42 @@ 
 #define AVR_CPU_IO_REGS_LAST (AVR_CPU_IO_REGS_BASE + AVR_CPU_IO_REGS - 1)
 #define AVR_EXT_IO_REGS_LAST (AVR_EXT_IO_REGS_BASE + AVR_EXT_IO_REGS - 1)
 
+enum    avr_features {
+    AVR_FEATURE_SRAM,
+
+    AVR_FEATURE_1_BYTE_PC,
+    AVR_FEATURE_2_BYTE_PC,
+    AVR_FEATURE_3_BYTE_PC,
+
+    AVR_FEATURE_1_BYTE_SP,
+    AVR_FEATURE_2_BYTE_SP,
+
+    AVR_FEATURE_BREAK,
+    AVR_FEATURE_DES,
+    AVR_FEATURE_RMW, /* Read Modify Write - XCH LAC LAS LAT */
+
+    AVR_FEATURE_EIJMP_EICALL,
+    AVR_FEATURE_IJMP_ICALL,
+    AVR_FEATURE_JMP_CALL,
+
+    AVR_FEATURE_ADIW_SBIW,
+
+    AVR_FEATURE_SPM,
+    AVR_FEATURE_SPMX,
+
+    AVR_FEATURE_ELPMX,
+    AVR_FEATURE_ELPM,
+    AVR_FEATURE_LPMX,
+    AVR_FEATURE_LPM,
+
+    AVR_FEATURE_MOVW,
+    AVR_FEATURE_MUL,
+    AVR_FEATURE_RAMPD,
+    AVR_FEATURE_RAMPX,
+    AVR_FEATURE_RAMPY,
+    AVR_FEATURE_RAMPZ,
+};
+
 typedef struct CPUAVRState CPUAVRState;
 
 struct CPUAVRState {
@@ -111,12 +147,24 @@  struct CPUAVRState {
 
     uint64_t intsrc; /* interrupt sources */
 
+    uint32_t features;
+
     /* Those resources are used only in QEMU core */
     CPU_COMMON
 };
 
-#define cpu_list            avr_cpu_list
-#define cpu_signal_handler  cpu_avr_signal_handler
+static inline int avr_feature(CPUAVRState *env, int feature)
+{
+    return (env->features & (1U << feature)) != 0;
+}
+
+static inline void  avr_set_feature(CPUAVRState *env, int feature)
+{
+    env->features |= (1U << feature);
+}
+
+#define cpu_list avr_cpu_list
+#define cpu_signal_handler cpu_avr_signal_handler
 
 #include "exec/cpu-all.h"
 #include "cpu-qom.h"
diff --git a/target-avr/machine.c b/target-avr/machine.c
index 9f20aed..2b005cc 100644
--- a/target-avr/machine.c
+++ b/target-avr/machine.c
@@ -44,8 +44,8 @@  static void put_sreg(QEMUFile *f, void *opaque, size_t size)
 
 static const VMStateInfo vms_sreg = {
     .name = "sreg",
-    .get  = get_sreg,
-    .put  = put_sreg,
+    .get = get_sreg,
+    .put = put_sreg,
 };
 
 static int get_segment(QEMUFile *f, void *opaque, size_t size)
@@ -68,33 +68,33 @@  static void put_segment(QEMUFile *f, void *opaque, size_t size)
 
 static const VMStateInfo vms_rampD = {
     .name = "rampD",
-    .get  = get_segment,
-    .put  = put_segment,
+    .get = get_segment,
+    .put = put_segment,
 };
 static const VMStateInfo vms_rampX = {
     .name = "rampX",
-    .get  = get_segment,
-    .put  = put_segment,
+    .get = get_segment,
+    .put = put_segment,
 };
 static const VMStateInfo vms_rampY = {
     .name = "rampY",
-    .get  = get_segment,
-    .put  = put_segment,
+    .get = get_segment,
+    .put = put_segment,
 };
 static const VMStateInfo vms_rampZ = {
     .name = "rampZ",
-    .get  = get_segment,
-    .put  = put_segment,
+    .get = get_segment,
+    .put = put_segment,
 };
 static const VMStateInfo vms_eind = {
     .name = "eind",
-    .get  = get_segment,
-    .put  = put_segment,
+    .get = get_segment,
+    .put = put_segment,
 };
 
 const VMStateDescription vms_avr_cpu = {
-    .name               = "cpu",
-    .version_id         = 0,
+    .name = "cpu",
+    .version_id = 0,
     .minimum_version_id = 0,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(env.pc_w, AVRCPU),