diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index 7ad8398..2bac71f 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -35,6 +35,7 @@
  * CRISCPUClass:
  * @parent_realize: The parent class' realize handler.
  * @parent_reset: The parent class' reset handler.
+ * @vr: Version Register value.
  *
  * A CRIS CPU model.
  */
@@ -45,6 +46,8 @@ typedef struct CRISCPUClass {
 
     DeviceRealize parent_realize;
     void (*parent_reset)(CPUState *cpu);
+
+    uint32_t vr;
 } CRISCPUClass;
 
 /**
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index fedf641..8008988 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -55,6 +55,84 @@ static void cris_cpu_reset(CPUState *s)
 #endif
 }
 
+static ObjectClass *cris_cpu_class_by_name(const char *cpu_model)
+{
+    ObjectClass *oc;
+    char *typename;
+
+    if (cpu_model == NULL) {
+        return NULL;
+    }
+
+    typename = g_strdup_printf("%s-" TYPE_CRIS_CPU, cpu_model);
+    oc = object_class_by_name(typename);
+    g_free(typename);
+    if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_CRIS_CPU) ||
+                       object_class_is_abstract(oc))) {
+        oc = NULL;
+    }
+    return oc;
+}
+
+CRISCPU *cpu_cris_init(const char *cpu_model)
+{
+    CRISCPU *cpu;
+    ObjectClass *oc;
+
+    oc = cris_cpu_class_by_name(cpu_model);
+    if (oc == NULL) {
+        return NULL;
+    }
+    cpu = CRIS_CPU(object_new(object_class_get_name(oc)));
+
+    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
+
+    return cpu;
+}
+
+/* Sort alphabetically by VR. */
+static gint cris_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+    CRISCPUClass *ccc_a = CRIS_CPU_CLASS(a);
+    CRISCPUClass *ccc_b = CRIS_CPU_CLASS(b);
+
+    /*  */
+    if (ccc_a->vr > ccc_b->vr) {
+        return 1;
+    } else if (ccc_a->vr < ccc_b->vr) {
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
+static void cris_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    ObjectClass *oc = data;
+    CPUListState *s = user_data;
+    const char *typename = object_class_get_name(oc);
+    char *name;
+
+    name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_CRIS_CPU));
+    (*s->cpu_fprintf)(s->file, "  %s\n", name);
+    g_free(name);
+}
+
+void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    CPUListState s = {
+        .file = f,
+        .cpu_fprintf = cpu_fprintf,
+    };
+    GSList *list;
+
+    list = object_class_get_list(TYPE_CRIS_CPU, false);
+    list = g_slist_sort(list, cris_cpu_list_compare);
+    (*cpu_fprintf)(f, "Available CPUs:\n");
+    g_slist_foreach(list, cris_cpu_list_entry, &s);
+    g_slist_free(list);
+}
+
 static void cris_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CRISCPU *cpu = CRIS_CPU(dev);
@@ -69,11 +147,14 @@ static void cris_cpu_realizefn(DeviceState *dev, Error **errp)
 static void cris_cpu_initfn(Object *obj)
 {
     CRISCPU *cpu = CRIS_CPU(obj);
+    CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj);
     CPUCRISState *env = &cpu->env;
     static bool tcg_initialized;
 
     cpu_exec_init(env);
 
+    env->pregs[PR_VR] = ccc->vr;
+
     if (tcg_enabled() && !tcg_initialized) {
         tcg_initialized = true;
         if (env->pregs[PR_VR] < 32) {
@@ -84,6 +165,69 @@ static void cris_cpu_initfn(Object *obj)
     }
 }
 
+static void crisv8_cpu_class_init(ObjectClass *oc, void *data)
+{
+    CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
+
+    ccc->vr = 8;
+}
+
+static void crisv9_cpu_class_init(ObjectClass *oc, void *data)
+{
+    CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
+
+    ccc->vr = 9;
+}
+
+static void crisv10_cpu_class_init(ObjectClass *oc, void *data)
+{
+    CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
+
+    ccc->vr = 10;
+}
+
+static void crisv11_cpu_class_init(ObjectClass *oc, void *data)
+{
+    CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
+
+    ccc->vr = 11;
+}
+
+static void crisv32_cpu_class_init(ObjectClass *oc, void *data)
+{
+    CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
+
+    ccc->vr = 32;
+}
+
+#define TYPE(model) model "-" TYPE_CRIS_CPU
+
+static const TypeInfo cris_cpu_model_type_infos[] = {
+    {
+        .name = TYPE("crisv8"),
+        .parent = TYPE_CRIS_CPU,
+        .class_init = crisv8_cpu_class_init,
+    }, {
+        .name = TYPE("crisv9"),
+        .parent = TYPE_CRIS_CPU,
+        .class_init = crisv9_cpu_class_init,
+    }, {
+        .name = TYPE("crisv10"),
+        .parent = TYPE_CRIS_CPU,
+        .class_init = crisv10_cpu_class_init,
+    }, {
+        .name = TYPE("crisv11"),
+        .parent = TYPE_CRIS_CPU,
+        .class_init = crisv11_cpu_class_init,
+    }, {
+        .name = TYPE("crisv32"),
+        .parent = TYPE_CRIS_CPU,
+        .class_init = crisv32_cpu_class_init,
+    }
+};
+
+#undef TYPE
+
 static void cris_cpu_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
@@ -95,6 +239,8 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
 
     ccc->parent_reset = cc->reset;
     cc->reset = cris_cpu_reset;
+
+    cc->class_by_name = cris_cpu_class_by_name;
 }
 
 static const TypeInfo cris_cpu_type_info = {
@@ -102,14 +248,19 @@ static const TypeInfo cris_cpu_type_info = {
     .parent = TYPE_CPU,
     .instance_size = sizeof(CRISCPU),
     .instance_init = cris_cpu_initfn,
-    .abstract = false,
+    .abstract = true,
     .class_size = sizeof(CRISCPUClass),
     .class_init = cris_cpu_class_init,
 };
 
 static void cris_cpu_register_types(void)
 {
+    int i;
+
     type_register_static(&cris_cpu_type_info);
+    for (i = 0; i < ARRAY_SIZE(cris_cpu_model_type_infos); i++) {
+        type_register_static(&cris_cpu_model_type_infos[i]);
+    }
 }
 
 type_init(cris_cpu_register_types)
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 25a43fa..04a5379 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3513,54 +3513,6 @@ void cpu_dump_state (CPUCRISState *env, FILE *f, fprintf_function cpu_fprintf,
 
 }
 
-struct
-{
-    uint32_t vr;
-    const char *name;
-} cris_cores[] = {
-    {8, "crisv8"},
-    {9, "crisv9"},
-    {10, "crisv10"},
-    {11, "crisv11"},
-    {32, "crisv32"},
-};
-
-void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf)
-{
-    unsigned int i;
-
-    (*cpu_fprintf)(f, "Available CPUs:\n");
-    for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
-        (*cpu_fprintf)(f, "  %s\n", cris_cores[i].name);
-    }
-}
-
-static uint32_t vr_by_name(const char *name)
-{
-    unsigned int i;
-    for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
-        if (strcmp(name, cris_cores[i].name) == 0) {
-            return cris_cores[i].vr;
-        }
-    }
-    return 32;
-}
-
-CRISCPU *cpu_cris_init(const char *cpu_model)
-{
-    CRISCPU *cpu;
-    CPUCRISState *env;
-
-    cpu = CRIS_CPU(object_new(TYPE_CRIS_CPU));
-    env = &cpu->env;
-
-    env->pregs[PR_VR] = vr_by_name(cpu_model);
-
-    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
-
-    return cpu;
-}
-
 void cris_initialize_tcg(void)
 {
     int i;
