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
